<!DOCTYPE HTML>
<html lang="zh-CN">


<head>
    <meta charset="utf-8">
    <meta name="keywords" content="Web项目中的安全设计, 博客 blog">
    <meta name="description" content="熊猫小二的博客  xmxe&#39;s blog">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <!-- 为了引用qq空间图床文件 -->
    <meta name="referrer" content="no-referrer">
    <!-- Global site tag (gtag.js) - Google Analytics -->


    <title>Web项目中的安全设计 | 熊猫小二</title>
    <link rel="icon" type="image/x-icon, image/vnd.microsoft.icon" href="/blog/favicon.ico">
    <link rel="stylesheet" type="text/css" href="/blog/libs/awesome/css/all.css">
    <link rel="stylesheet" type="text/css" href="/blog/libs/materialize/materialize.min.css">
    <link rel="stylesheet" type="text/css" href="/blog/libs/aos/aos.css">
    <link rel="stylesheet" type="text/css" href="/blog/libs/animate/animate.min.css">
    <link rel="stylesheet" type="text/css" href="/blog/libs/lightGallery/css/lightgallery.min.css">
    <link rel="stylesheet" type="text/css" href="/blog/css/matery.css">
    <link rel="stylesheet" type="text/css" href="/blog/css/my.css">
    <link rel="stylesheet" type="text/css" href="/blog/css/loading.css">

    <script src="/blog/libs/jquery/jquery.min.js"></script>

<meta name="generator" content="Hexo 6.3.0"></head>



   
<style>
    body{
       background-image: url(/blog/medias/cover.jpg);
       background-repeat:no-repeat;
       background-size:cover;
       background-attachment:fixed;
    }
</style>



<body>
    
  <div id="loading-box">
    <div class="loading-left-bg"></div>
    <div class="loading-right-bg"></div>
    <div class="spinner-box">
      <div class="configure-border-1">
        <div class="configure-core"></div>
      </div>
      <div class="configure-border-2">
        <div class="configure-core"></div>
      </div>
      <div class="loading-word">加载中...</div>
    </div>
  </div>
  <!-- 页面加载动画 -->
  <script>
    $(document).ready(function () {
      // document.body.style.overflow = 'auto';
      document.getElementById('loading-box').classList.add("loaded")
    })
  </script>

    <header class="navbar-fixed">
    <nav id="headNav" class="bg-color nav-transparent">
        <div id="navContainer" class="nav-wrapper container">
            <div class="brand-logo">
                <a href="/blog/" class="waves-effect waves-light">
                    
                        <img src="/blog/medias/logo.png" class="logo-img" alt="LOGO">
                    
                    <span class="logo-span">熊猫小二</span>
                </a>
            </div>
            

<a href="#" data-target="mobile-nav" class="sidenav-trigger button-collapse"><i class="fas fa-bars"></i></a>
<ul class="right nav-menu">
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/blog/" class="waves-effect waves-light">
      
      <i class="fas fa-home" style="zoom: 0.6;"></i>
      
      <span>首页</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="#" class="waves-effect waves-light">

      
      <i class="fas fa-book" style="zoom: 0.6;"></i>
      
      <span>归档</span>
      <i class="fas fa-chevron-down" aria-hidden="true" style="zoom: 0.6;"></i>
    </a>
    <ul class="sub-nav menus_item_child ">
      
      <li>
        <a href="/blog/archives">
          
          <i class="fas fa-archive" style="margin-top: -20px; zoom: 0.6;"></i>
          
          <span>归档</span>
        </a>
      </li>
      
      <li>
        <a href="/blog/tags">
          
          <i class="fas fa-tags" style="margin-top: -20px; zoom: 0.6;"></i>
          
          <span>标签</span>
        </a>
      </li>
      
      <li>
        <a href="/blog/categories">
          
          <i class="fas fa-bookmark" style="margin-top: -20px; zoom: 0.6;"></i>
          
          <span>分类</span>
        </a>
      </li>
      
    </ul>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/blog/friends" class="waves-effect waves-light">
      
      <i class="fas fa-address-book" style="zoom: 0.6;"></i>
      
      <span>友链</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="#" class="waves-effect waves-light">

      
      <i class="fas fa-user-circle" style="zoom: 0.6;"></i>
      
      <span>关于</span>
      <i class="fas fa-chevron-down" aria-hidden="true" style="zoom: 0.6;"></i>
    </a>
    <ul class="sub-nav menus_item_child ">
      
      <li>
        <a href="/blog/about">
          
          <i class="fas fa-star-of-david" style="margin-top: -20px; zoom: 0.6;"></i>
          
          <span>主页</span>
        </a>
      </li>
      
      <li>
        <a href="/blog/gallery">
          
          <i class="fas fa-images" style="margin-top: -20px; zoom: 0.6;"></i>
          
          <span>相册</span>
        </a>
      </li>
      
    </ul>
    
  </li>
  
  <li>
    <a href="#searchModal" class="modal-trigger waves-effect waves-light">
      <i id="searchIcon" class="fas fa-search" title="搜索" style="zoom: 0.85;"></i>
    </a>
  </li>
  
    <li>
      <a class="waves-effect waves-light" onclick="switchNightMode()">
        <i id="sum-moon-icon" class="fas fa-sun" style="zoom:0.65;" title="切换主题"></i>
      </a>
    </li>
  
  
</ul>


<div id="mobile-nav" class="side-nav sidenav">

    <div class="mobile-head bg-color">
        
          <img src="/blog/medias/logo.png" class="logo-img circle responsive-img">
        
        <div class="logo-name">熊猫小二</div>
        <div class="logo-desc">
            
            熊猫小二的博客  xmxe&#39;s blog
            
        </div>
    </div>

    

    <ul class="menu-list mobile-menu-list">
        
        <li class="m-nav-item">
	  
		<a href="/blog/" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-home"></i>
			
			首页
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="javascript:;">
			
				<i class="fa-fw fas fa-book"></i>
			
			归档
			<span class="m-icon"><i class="fas fa-chevron-right"></i></span>
		</a>
            <ul  >
              
                <li>

                  <a href="/blog/archives " style="margin-left:75px">
				  
				   <i class="fa fas fa-archive" style="position: absolute;left:50px" ></i>
			      
		          <span>归档</span>
                  </a>
                </li>
              
                <li>

                  <a href="/blog/tags " style="margin-left:75px">
				  
				   <i class="fa fas fa-tags" style="position: absolute;left:50px" ></i>
			      
		          <span>标签</span>
                  </a>
                </li>
              
                <li>

                  <a href="/blog/categories " style="margin-left:75px">
				  
				   <i class="fa fas fa-bookmark" style="position: absolute;left:50px" ></i>
			      
		          <span>分类</span>
                  </a>
                </li>
              
            </ul>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/blog/friends" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-address-book"></i>
			
			友链
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="javascript:;">
			
				<i class="fa-fw fas fa-user-circle"></i>
			
			关于
			<span class="m-icon"><i class="fas fa-chevron-right"></i></span>
		</a>
            <ul  >
              
                <li>

                  <a href="/blog/about " style="margin-left:75px">
				  
				   <i class="fa fas fa-star-of-david" style="position: absolute;left:50px" ></i>
			      
		          <span>主页</span>
                  </a>
                </li>
              
                <li>

                  <a href="/blog/gallery " style="margin-left:75px">
				  
				   <i class="fa fas fa-images" style="position: absolute;left:50px" ></i>
			      
		          <span>相册</span>
                  </a>
                </li>
              
            </ul>
          
        </li>
        
        
    </ul>
</div>


        </div>

        
    </nav>

</header>

    
<script src="/blog/libs/cryptojs/crypto-js.min.js"></script>
<script>
    (function() {
        let pwd = '';
        if (pwd && pwd.length > 0) {
            if (pwd !== CryptoJS.SHA256(prompt('请输入访问本文章的密码')).toString(CryptoJS.enc.Hex)) {
                alert('密码错误，将返回主页！');
                location.href = '/blog/';
            }
        }
    })();
</script>




<div class="bg-cover pd-header post-cover" style="background-image: url('/blog/medias/featureimages/9.jpg')">
    <div class="container" style="right: 0px;left: 0px;">
        <div class="row">
            <div class="col s12 m12 l12">
                <div class="brand">
                    <h1 id="post-title" class="description center-align post-title"></h1>

                    
                        <!-- <script src="https://cdn.jsdelivr.net/npm/typed.js@2.0.11"></script> -->
                        <script>
                            var typedObj = new Typed("#post-title", {
                                strings: [ 'Web项目中的安全设计' ],
                                startDelay: 300,
                                typeSpeed: 70,
                                loop: false,
                                backSpeed: 50,
                                showCursor: true
                            });
                        </script>
                    
                </div>
            </div>
        </div>
    </div>
</div>




<main class="post-container content">

    
    <link rel="stylesheet" href="/blog/libs/tocbot/tocbot.css">
<style>
    #articleContent h1::before,
    #articleContent h2::before,
    #articleContent h3::before,
    #articleContent h4::before,
    #articleContent h5::before,
    #articleContent h6::before {
        display: block;
        content: " ";
        height: 100px;
        margin-top: -100px;
        visibility: hidden;
    }

    #articleContent :focus {
        outline: none;
    }

    .toc-fixed {
        position: fixed;
        top: 64px;
    }

    .toc-widget {
        width: 345px;
        padding-left: 20px;
        background-color: rgb(255, 255, 255,0.7);
        border-radius: 10px;
        box-shadow: 0 10px 35px 2px rgba(0, 0, 0, .15), 0 5px 15px rgba(0, 0, 0, .07), 0 2px 5px -5px rgba(0, 0, 0, .1) !important;
    }

    .toc-widget .toc-title {
        padding: 35px 0 15px 17px;
        font-size: 1.5rem;
        font-weight: bold;
        line-height: 1.5rem;
    }

    .toc-widget ol {
        padding: 0;
        list-style: none;
    }

    #toc-content {
        padding-bottom: 30px;
        overflow: auto;
        max-height: 480px;
    }

    #toc-content ol {
        padding-left: 10px;
    }

    #toc-content ol li {
        padding-left: 10px;
    }

    #toc-content .toc-link:hover {
        color: #42b983;
        font-weight: 700;
        text-decoration: underline;
    }

    #toc-content .toc-link::before {
        background-color: transparent;
        max-height: 25px;

        position: absolute;
        right: 23.5vw;
        display: block;
    }

    #toc-content .is-active-link {
        color: #42b983;
    }

    #floating-toc-btn {
        position: fixed;
        right: 15px;
        bottom: 76px;
        padding-top: 15px;
        margin-bottom: 0;
        z-index: 998;
    }

    #floating-toc-btn .btn-floating {
        width: 48px;
        height: 48px;
    }

    #floating-toc-btn .btn-floating i {
        line-height: 48px;
        font-size: 1.4rem;
    }
</style>
<div class="row">
    <div id="main-content" class="col s12 m12 l9">
        <!-- 文章内容详情 -->
<div id="artDetail">
    <div class="card">
        <div class="card-content article-info">
            <div class="row tag-cate">
                <div class="col s7">
                    
                    <div class="article-tag">
                        
                            <a href="/blog/tags/%E4%BB%A3%E7%A0%81%E5%AE%9E%E6%88%98/">
                                <span class="chip bg-color">代码实战</span>
                            </a>
                        
                    </div>
                    
                </div>
                <div class="col s5 right-align">
                    
                </div>
            </div>

            <div class="post-info">
                

                

                

                

                
            </div>
        </div>
        <hr class="clearfix">

        
        <!-- 是否加载使用自带的 prismjs. -->
        <link rel="stylesheet" href="/blog/libs/prism/prism.css">
        

        
        <!-- 代码块折行 -->
        <style type="text/css">
            code[class*="language-"], pre[class*="language-"] { white-space: pre-wrap !important; }
        </style>
        

        <div class="card-content article-card-content">
            <div id="articleContent">
                <h2 id="完整性校验"><a href="#完整性校验" class="headerlink" title="完整性校验"></a>完整性校验</h2><p><strong>描述</strong></p>
<p>数据传输完整性是指数据在传输过程中，不被未授权的篡改或在篡改后能够被迅速发现。</p>
<p><strong>防护建议</strong></p>
<ol>
<li>传输过程中数据做整体加密处理（该方案存在一定风险，若攻击者拥有系统访问权限，可在数据未解密的情况下直接篡改加密数据，进行提权操作，固未从根本上解决数据完整性问题，建议采用方案2）</li>
<li>数据签名校验：建立客户端和服务端全流程校验和处理机制，有效解决数据在请求和响应传输过程中被篡改的问题，提高数据双向传输完整性，用以保障信息系统安全。为保证数据的完整性，约定uid为密钥（uid的生成和传输机制详见<a href="#uid%E7%9A%84%E7%94%9F%E6%88%90%E5%92%8C%E4%BC%A0%E8%BE%93%E6%96%B9%E6%A1%88">uid的生成和传输方案</a>）用于签名计算。</li>
</ol>
<p>系统应采用校验码技术或密码技术保证鉴别信息和重要业务数据等敏感信息在传输过程中的完整性。<br>    ①等保三级要求：系统鉴别信息和重要业务数据等敏感信息在传输过程中应采用国家密码主管部门要求的加密算法（SM3等）对其进行数据完整性校验<br>    ②等保二级要求：系统中的鉴别信息和重要业务数据等敏感信息在传输过程中应采用校验码技术或密码技术（MD5、SHA等）对其进行数据完整性校验</p>
<p><strong>请求传输完整性校验实现方案</strong></p>
<p>（1）客户端从localstorage中读取加固参数uid和时间差△timestamp（服务器时间与客户端时间的时间差），并计算请求发送时的服务端当前时间戳为:客户端当前时间+△timestamp。<br>（2）客户端使用散列算法对请求数据data和关键加固参数uid，timestamp进行签名计算，以国密算法SM3举例：<code>clientSM3=SM3(sort(data+salt+timestamp))</code>,sort的含义是将参数值按照字母字典排序，然后从小到大拼接成一个字符串。<br>（3）将签名clientSM3和时间戳以参数或自定义header的形式随请求发送给服务器。<br>（4）服务端收到请求，判断请求中是否存在clientSM3和时间戳参数，若不存在则请求无效，并向客户端返回请求无效；若存在，则读取并继续执行。<br>（5）服务端验证时间戳参数，服务端当前时间timestamp_now-timestamp是否大于60s或&lt;-5s（默认一次HTTP请求从发出到到达服务器的时间是不会超过60s的，且不会小于0，考虑到计算机精度和多网关业务场景，故判断条件为&gt;60s或&lt;-5s）。若大于60s或&lt;-5s，则请求无效；反之为有效请求，。<br>（6）服务端验证clientSM3参数，服务端根据请求的会话标识读取该用户的uid参数，并记录请求中的timestamp、请求数据data，调用签名生成算法，得到<code>serverSM3=SM3(sort(data+uid+timestamp))</code>，验证serverSM3是否等于clientSM3，若不一致，则请求无效，并向客户端返回数据请求被篡改；若一致说明数据未篡改，进行下一步业务处理。</p>
<p><img src="/blog/images/%E8%AF%B7%E6%B1%82%E4%BC%A0%E8%BE%93%E5%AE%8C%E6%95%B4%E6%80%A7.png"></p>
<p><strong>响应传输完整性校验实现方案</strong></p>
<p>（1）服务端返回响应前根据会话标识读取该用户的uid参数，并获取当前服务端时间timestamp<br>（2）服务端使用散列算法对响应数据data和salt值进行签名计算，以国密SM3举例：<code>serverSM3=SM3(sort(data+uid+timestamp))</code>,sort的含义是将参数值按照字母字典排序，然后从小到大拼接成一个字符串。<br>（3）将签名serverSM3和timestamp以参数或自定义header的形式随响应发送给客户端。<br>（4）客户端收到响应后判断响应中是否存在serverSM3和timestamp参数，若不存在则响应无效，客户端不再解析该响应；若存在，则读取并继续执行。<br>（5）验证timestamp参数，客户端当前时间timestamp_now-timestamp是否大于60s或&lt;-5s（默认一次HTTP响应从发出到到达客户端的时间是不会超过60s的，且不会小于0，考虑到计算机精度和多网关业务场景，故判断条件为&gt;60s或&lt;-5s）。若大于60s或&lt;-5s，则响应无效；反之则继续执行。<br>（6）验证serverSM3参数，客户端读取该用户的盐值uid，并记录响应中的timestamp、响应数据data，调用签名生成算法，得到clientSM3&#x3D;SM3(sort(data+salt+timestamp))，验证clientSM3是否等于serverSM3，若不一致，则响应无效，说明响应数据被篡改；若一致说明数据未篡改，响应正常，则客户端对响应解析并进行下一步处理。</p>
<p><img src="/blog/images/%E5%93%8D%E5%BA%94%E4%BC%A0%E8%BE%93%E5%AE%8C%E6%95%B4%E6%80%A7.png"></p>
<p><strong>简明扼要</strong></p>
<p>1、传输过程中数据加密处理<br>2、数据签名校验：为保证数据的完整性，约定uid为密钥（仅一次会话周期有效，且仅客户端和服务端知道，在传输中不可见）用于签名计算，客户端发送请求时，将请求内容与uid结合计算出签名；服务端接收到请求后，也按相同算法计算出签名。如果相等，则请求来自可信任客户端，且请求是完整的。<br>    ①客户端使用哈希算法对请求中数据和salt值进行签名计算（本方案中uid取为salt值）sign_client&#x3D;md5(sort(data+uid)),sort的含义是将参数值按照字母字典排序，然后从小到大拼接成一个字符串。<br>    ②将签名sign_client以参数的形式发送给服务器<br>    ③服务器收到数据之后，根据用户会话读取uid，对数据使用相同的哈希算法进行签名计算sign_server&#x3D;md5(sort(data+uid))<br>    ④验证sign_client和sign_server是否一致，若一致则说明数据没有经过篡改，执行响应操作，若不一致，则签名校验异常，数据经过篡改视为无效请求。</p>
<p><img src="/blog/images/%E5%AE%8C%E6%95%B4%E6%80%A7%E6%A0%A1%E9%AA%8C%E6%B5%81%E7%A8%8B.png"></p>
<p><strong>代码实现</strong></p>
<pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token comment">// Spring拦截器实现</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>net<span class="token punctuation">.</span></span><span class="token class-name">URLDecoder</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Arrays</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Enumeration</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Map</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Objects</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>http<span class="token punctuation">.</span></span><span class="token class-name">HttpServletRequest</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>http<span class="token punctuation">.</span></span><span class="token class-name">HttpServletResponse</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>bouncycastle<span class="token punctuation">.</span>crypto<span class="token punctuation">.</span>digests<span class="token punctuation">.</span></span><span class="token class-name">SM3Digest</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>bouncycastle<span class="token punctuation">.</span>util<span class="token punctuation">.</span>encoders<span class="token punctuation">.</span></span><span class="token class-name">Hex</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Assert</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>web<span class="token punctuation">.</span>method<span class="token punctuation">.</span></span><span class="token class-name">HandlerMethod</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>web<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>handler<span class="token punctuation">.</span></span><span class="token class-name">HandlerInterceptorAdapter</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">cn<span class="token punctuation">.</span>hutool<span class="token punctuation">.</span>core<span class="token punctuation">.</span>net<span class="token punctuation">.</span></span><span class="token class-name">URLEncodeUtil</span></span><span class="token punctuation">;</span>

<span class="token comment">/**
 * 数据完整性校验
 */</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">IntegralityCheckInterceptor</span> <span class="token keyword">extends</span> <span class="token class-name">HandlerInterceptorAdapter</span> <span class="token punctuation">&#123;</span><span class="token comment">// implements HandlerInterceptor</span>

	<span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">preHandle</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> request<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> response<span class="token punctuation">,</span> <span class="token class-name">Object</span> handler<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">&#123;</span>
		
		<span class="token keyword">if</span> <span class="token punctuation">(</span>handler <span class="token keyword">instanceof</span> <span class="token class-name">HandlerMethod</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token comment">//            HandlerMethod handlerMethod = (HandlerMethod) handler;</span>
		       <span class="token class-name">String</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> white <span class="token operator">=</span><span class="token punctuation">&#123;</span><span class="token string">"downLoadFromFTP"</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
		        <span class="token class-name">String</span> path <span class="token operator">=</span>request<span class="token punctuation">.</span><span class="token function">getServletPath</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> white<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
		            <span class="token keyword">if</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span>white<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">!=</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
		            	<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
		            <span class="token punctuation">&#125;</span>
		        <span class="token punctuation">&#125;</span>
        	<span class="token comment">//客户端时间+△timestamp，即发送请求时的服务端的当前时间</span>
			<span class="token keyword">try</span> <span class="token punctuation">&#123;</span>
                <span class="token class-name">Long</span> timestamp <span class="token operator">=</span> <span class="token class-name">Long</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span><span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token string">"timestamp"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token comment">// 客户端使用散列算法对请求数据data和关键加固参数uid，timestamp进行签名计算</span>
                <span class="token class-name">String</span> clientSM3 <span class="token operator">=</span> request<span class="token punctuation">.</span><span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token string">"clientSM3"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token class-name">Objects</span><span class="token punctuation">.</span><span class="token function">nonNull</span><span class="token punctuation">(</span>timestamp<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token class-name">Objects</span><span class="token punctuation">.</span><span class="token function">nonNull</span><span class="token punctuation">(</span>clientSM3<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                    <span class="token comment">// 失效时间</span>
                    <span class="token keyword">int</span> seconds <span class="token operator">=</span> <span class="token number">60</span><span class="token punctuation">;</span>
                    <span class="token comment">// 服务器当前时间</span>
                    <span class="token keyword">long</span> currentTime <span class="token operator">=</span> <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">currentTimeMillis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">long</span> timeDiff <span class="token operator">=</span> currentTime <span class="token operator">-</span> timestamp<span class="token punctuation">;</span>
                    <span class="token comment">// 默认一次HTTP请求从发出到到达服务器的时间是不会超过60s的，且不会小于0，考虑到计算机精度和多网关业务场景，故判断条件为>60s或&lt;-5s</span>
                    <span class="token keyword">if</span><span class="token punctuation">(</span>timeDiff <span class="token operator">></span> seconds <span class="token operator">*</span> <span class="token number">1000</span> <span class="token operator">||</span> timeDiff <span class="token operator">&lt;</span> <span class="token operator">-</span><span class="token number">5</span> <span class="token operator">*</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                        <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
                    <span class="token punctuation">&#125;</span>

                    <span class="token comment">// 验证clientSM3参数</span>
                    <span class="token comment">// 服务端根据请求的会话标识读取该用户的uid参数</span>
                    <span class="token class-name">String</span> uid <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">)</span> request<span class="token punctuation">.</span><span class="token function">getSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">"uid"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token class-name">Assert</span><span class="token punctuation">.</span><span class="token function">notNull</span><span class="token punctuation">(</span>uid<span class="token punctuation">)</span><span class="token punctuation">;</span>

                    <span class="token comment">// 请求数据data</span>
                    <span class="token class-name">String</span> data <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">;</span>
                    <span class="token class-name">Map</span><span class="token operator">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">></span> paramMap <span class="token operator">=</span> request<span class="token punctuation">.</span><span class="token function">getParameterMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">if</span><span class="token punctuation">(</span>paramMap<span class="token operator">!=</span><span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>paramMap<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                        <span class="token class-name">StringBuilder</span> sb <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StringBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token class-name">Map<span class="token punctuation">.</span>Entry</span><span class="token operator">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">></span> entry <span class="token operator">:</span> paramMap<span class="token punctuation">.</span><span class="token function">entrySet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                            <span class="token class-name">String</span> key <span class="token operator">=</span> entry<span class="token punctuation">.</span><span class="token function">getKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                            <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> value <span class="token operator">=</span> entry<span class="token punctuation">.</span><span class="token function">getValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                            <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token class-name">String</span> paramValue <span class="token operator">:</span> value<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                                sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">;</span>
                                sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"="</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                                <span class="token class-name">String</span> param <span class="token operator">=</span> paramValue<span class="token punctuation">.</span><span class="token function">replaceAll</span><span class="token punctuation">(</span><span class="token string">" "</span><span class="token punctuation">,</span><span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                                <span class="token class-name">String</span> deparam<span class="token punctuation">;</span>
                                <span class="token keyword">try</span> <span class="token punctuation">&#123;</span>
                                    deparam <span class="token operator">=</span> <span class="token class-name">URLDecoder</span><span class="token punctuation">.</span><span class="token function">decode</span><span class="token punctuation">(</span>param<span class="token punctuation">,</span><span class="token string">"UTF-8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                                <span class="token punctuation">&#125;</span><span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                                    <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
                                <span class="token punctuation">&#125;</span>
                                <span class="token comment">// String deparam = URLDecoder.decode(param,"UTF-8");</span>
                                sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>deparam<span class="token punctuation">)</span><span class="token punctuation">;</span>
                                sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"&amp;"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                            <span class="token punctuation">&#125;</span>          			
                        <span class="token punctuation">&#125;</span>
                        <span class="token class-name">String</span> strParam <span class="token operator">=</span> sb<span class="token punctuation">.</span><span class="token function">substring</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> sb<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        data <span class="token operator">=</span> <span class="token class-name">URLEncodeUtil</span><span class="token punctuation">.</span><span class="token function">encodeAll</span><span class="token punctuation">(</span>strParam<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token punctuation">&#125;</span>	
                    <span class="token comment">// 调用签名算法serverSM3=SM3(sort(data+uid+timestamp))</span>
                    <span class="token keyword">char</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c <span class="token operator">=</span> <span class="token punctuation">(</span>data<span class="token operator">+</span>uid<span class="token operator">+</span>timestamp<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toCharArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token class-name">Arrays</span><span class="token punctuation">.</span><span class="token function">sort</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token class-name">String</span> sort <span class="token operator">=</span> <span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token class-name">String</span> serverSM3 <span class="token operator">=</span> <span class="token function">generateSM3HASH</span><span class="token punctuation">(</span>sort<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">if</span><span class="token punctuation">(</span>serverSM3<span class="token punctuation">.</span><span class="token function">equalsIgnoreCase</span><span class="token punctuation">(</span>clientSM3<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                        <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
                    <span class="token punctuation">&#125;</span>
                <span class="token punctuation">&#125;</span>
			<span class="token punctuation">&#125;</span><span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
				<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
			<span class="token punctuation">&#125;</span>
			<span class="token class-name">StringBuffer</span> url <span class="token operator">=</span> request<span class="token punctuation">.</span><span class="token function">getRequestURL</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>	
            <span class="token keyword">return</span> <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">preHandle</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> response<span class="token punctuation">,</span> handler<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
	<span class="token punctuation">&#125;</span>
	
	<span class="token comment">//摘要计算</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">generateSM3HASH</span><span class="token punctuation">(</span><span class="token class-name">String</span> src<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> md <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token number">32</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> msg1 <span class="token operator">=</span> src<span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">//System.out.println(Util.byteToHex(msg1));</span>
        <span class="token class-name">SM3Digest</span> sm3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM3Digest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        sm3<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>msg1<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> msg1<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
        sm3<span class="token punctuation">.</span><span class="token function">doFinal</span><span class="token punctuation">(</span>md<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> s <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token class-name">Hex</span><span class="token punctuation">.</span><span class="token function">encode</span><span class="token punctuation">(</span>md<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> s<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// jQuery ajaxhook.min.js插件实现</span>
<span class="token comment">// 接口拦截-数据完整性校验-防重放策略</span>
<span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 字母字典排序</span>
    <span class="token keyword">const</span> <span class="token function-variable function">dictSort</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">str</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">const</span> strArr <span class="token operator">=</span> <span class="token function">String</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> strArr<span class="token punctuation">.</span><span class="token function">sort</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> <span class="token function-variable function">randomStr</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">len <span class="token operator">=</span> <span class="token number">36</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">let</span> <span class="token function-variable function">randStr</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">var</span> array <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Uint32Array</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            window<span class="token punctuation">.</span>crypto<span class="token punctuation">.</span><span class="token function">getRandomValues</span><span class="token punctuation">(</span>array<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span>  array<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
        <span class="token keyword">let</span> str <span class="token operator">=</span> <span class="token function">randStr</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">do</span> <span class="token punctuation">&#123;</span>
            str <span class="token operator">+=</span> <span class="token function">randStr</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">while</span> <span class="token punctuation">(</span>str<span class="token punctuation">.</span>length <span class="token operator">&lt;</span> len<span class="token punctuation">)</span>
        <span class="token keyword">return</span> str<span class="token punctuation">.</span><span class="token function">substr</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> len<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
    ah<span class="token punctuation">.</span><span class="token function">proxy</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
        <span class="token comment">// 请求发起前进入</span>
        <span class="token function-variable function">onRequest</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">config<span class="token punctuation">,</span> handler</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>config<span class="token punctuation">.</span>url<span class="token operator">===</span><span class="token string">"update.do"</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                handler<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span><span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>config<span class="token punctuation">.</span>url<span class="token operator">===</span><span class="token string">"add.do"</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                handler<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span><span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
                <span class="token keyword">let</span> body <span class="token operator">=</span> config<span class="token punctuation">.</span>body <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">;</span>
                <span class="token comment">// 兼容formdata上传文件</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>body<span class="token operator">?.</span>constructor<span class="token punctuation">.</span>name <span class="token operator">===</span> <span class="token string">'FormData'</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                    <span class="token keyword">const</span> formDataStr <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
                    body<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">val<span class="token punctuation">,</span> key</span><span class="token punctuation">)</span> <span class="token operator">=></span> formDataStr<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> val<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">delete</span> formDataStr<span class="token punctuation">.</span>file<span class="token punctuation">;</span>
                    body <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>formDataStr<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">it</span> <span class="token operator">=></span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>it<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>formDataStr<span class="token punctuation">[</span>it<span class="token punctuation">]</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'&amp;'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">&#125;</span>
                <span class="token keyword">const</span> url <span class="token operator">=</span> config<span class="token punctuation">.</span>url<span class="token punctuation">;</span>
                <span class="token keyword">let</span> getUrl <span class="token operator">=</span> url<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'?'</span><span class="token punctuation">)</span> <span class="token operator">?</span> url<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">'?'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">;</span>
                <span class="token keyword">let</span> data <span class="token operator">=</span> <span class="token string">''</span>
                <span class="token keyword">if</span><span class="token punctuation">(</span>body<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                    <span class="token keyword">if</span><span class="token punctuation">(</span>getUrl<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                        body <span class="token operator">=</span> body <span class="token operator">+</span> <span class="token string">"&amp;"</span> <span class="token operator">+</span> getUrl<span class="token punctuation">;</span>
                    <span class="token punctuation">&#125;</span>
                <span class="token punctuation">&#125;</span><span class="token keyword">else</span><span class="token punctuation">&#123;</span>
                    body <span class="token operator">+=</span> getUrl
                <span class="token punctuation">&#125;</span>
                <span class="token keyword">if</span><span class="token punctuation">(</span>body <span class="token operator">===</span> <span class="token string">'&#123;&#125;'</span><span class="token punctuation">)</span> body <span class="token operator">=</span> <span class="token string">''</span>
                <span class="token keyword">let</span> decodeURI <span class="token operator">=</span> <span class="token function">decodeURIComponent</span><span class="token punctuation">(</span>body<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\+</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span><span class="token string">""</span><span class="token punctuation">)</span>
                data <span class="token operator">=</span> <span class="token function">encodeURIComponent</span><span class="token punctuation">(</span>decodeURI<span class="token punctuation">)</span>
                <span class="token keyword">const</span> uid <span class="token operator">=</span> localStorage<span class="token punctuation">.</span><span class="token function">getItem</span><span class="token punctuation">(</span><span class="token string">'uid'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token comment">// 获取时间差值</span>
                <span class="token keyword">const</span> timestamp <span class="token operator">=</span> localStorage<span class="token punctuation">.</span><span class="token function">getItem</span><span class="token punctuation">(</span><span class="token string">'timestamp'</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token number">0</span><span class="token punctuation">;</span>
                <span class="token comment">// serverTime = now - 差值</span>
                <span class="token keyword">const</span> serverTimestamp <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token function">Number</span><span class="token punctuation">(</span>timestamp<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token comment">// 参数按字母字典sort排序</span>
                <span class="token keyword">const</span> clientVal <span class="token operator">=</span> <span class="token function">dictSort</span><span class="token punctuation">(</span>data <span class="token operator">+</span> uid <span class="token operator">+</span> serverTimestamp<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token comment">// sm3加密</span>
                <span class="token keyword">const</span> clientSM3 <span class="token operator">=</span> <span class="token function">sm3</span><span class="token punctuation">(</span>clientVal<span class="token punctuation">)</span><span class="token punctuation">;</span>
                config<span class="token punctuation">.</span>headers<span class="token punctuation">.</span>clientSM3 <span class="token operator">=</span> clientSM3<span class="token punctuation">;</span>
                config<span class="token punctuation">.</span>headers<span class="token punctuation">.</span>timestamp <span class="token operator">=</span> serverTimestamp<span class="token punctuation">;</span>
                <span class="token comment">// 防重放策略参数</span>
                <span class="token keyword">const</span> nonce_client <span class="token operator">=</span> <span class="token function">randomStr</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">const</span> sign_client <span class="token operator">=</span> <span class="token function">sm3</span><span class="token punctuation">(</span>serverTimestamp <span class="token operator">+</span> nonce_client <span class="token operator">+</span> uid<span class="token punctuation">)</span><span class="token punctuation">;</span>
                config<span class="token punctuation">.</span>headers<span class="token punctuation">.</span>nonce_client <span class="token operator">=</span> nonce_client<span class="token punctuation">;</span>
                config<span class="token punctuation">.</span>headers<span class="token punctuation">.</span>sign_client <span class="token operator">=</span> sign_client<span class="token punctuation">;</span>
                handler<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>

        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
        <span class="token function-variable function">onError</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> handler</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
            handler<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
        <span class="token function-variable function">onResponse</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">response<span class="token punctuation">,</span> handler</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
            handler<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>response<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h2 id="防重放"><a href="#防重放" class="headerlink" title="防重放"></a>防重放</h2><p><strong>描述</strong></p>
<p>重放攻击（ReplayAttacks），是指攻击者发送一个目的主机已接收过的包，来达到欺骗系统的目的。</p>
<p>主机A要给服务器B发送数据请求，重放攻击可由发起者A或攻击者C发起。<br>※若由发起者A发起，A会恶意重复发送数据请求；<br>※若由攻击者C发起，攻击者可利用网络监听或者其他方式盗取用户数据请求，再重发该请求给服务器。</p>
<p><strong>防护建议</strong></p>
<ol>
<li>验证码机制<br>设置验证码，一次有效，每次请求更新新的验证码。适用于登录过程。优点：简单易实现。缺点：影响用户使用。</li>
<li>随机数机制（挑战与应答的机制）<br>客户端请求服务器时，服务器生成一个随机数返回给客户端，客户端带上这个随机数访问服务器，服务器比对客户端的这个参数，若相同，说明正确，不是重放攻击。<br>方案漏洞：<br>将获取随机数的请求和正常数据请求放到请求集合中，并设置全局变量。将响应返回的随机数赋值给全局变量，然后再将全局变量的值赋值给数据请求从而可保证每个请求均带入有效的随机数，重放该请求集合，从而达到重放攻击的目的。</li>
</ol>
<p><img src="/blog/images/%E9%9A%8F%E6%9C%BA%E6%95%B0%E9%98%B2%E9%87%8D%E6%94%BE.png"></p>
<ol start="3">
<li>时间戳+nonce+签名验证（推荐使用方案）<br>客户端发送请求时带上当前时间戳，并生成随机nonce，同时签名（签名是为了防止会话被劫持，时间戳和nonce参数被篡改)，服务端对请求时间戳、nonce及签名进行验证，一致则认为是有效请求，否则视为无效请求。</li>
</ol>
<p>参数说明</p>
<table>
<thead>
<tr>
<th align="center">参数</th>
<th align="center">类型</th>
<th align="center">说明</th>
</tr>
</thead>
<tbody><tr>
<td align="center">sign</td>
<td align="center">String</td>
<td align="center">请求加密签名，sign的计算结合了请求中的timestamp、nonce、uid以及<strong>加密的消息体</strong>（加入消息体计算sign，可保证请求数据完整性校验）。</td>
</tr>
<tr>
<td align="center">timestamp</td>
<td align="center">Integer</td>
<td align="center">时间戳，首次访问系统从服务端获取，与nonce结合使用，用于防止请求重放攻击。</td>
</tr>
<tr>
<td align="center">nonce</td>
<td align="center">String</td>
<td align="center">随机数，与timestamp结合使用，用于防止请求重放攻击。</td>
</tr>
<tr>
<td align="center">uid</td>
<td align="center">Sting</td>
<td align="center">用于计算签名和加密数据的key，与用户会话相关且生命周期与之一致，由服务端生成，经加密传输到客户端。</td>
</tr>
</tbody></table>
<p><strong>详细解决方案</strong></p>
<ol>
<li>用户访问系统，向服务端请求当前系统时间</li>
<li>客户端接收服务端返回的当前系统时间timestamp_server，并计算出与当前客户端时间的差值△timestamp，将其存入浏览器localstorage中。（加固相关信息存储到localstorage中而不是sessionstorage中，是为了防止客户端浏览器跨页面操作时获取不到相关参数）后续时间戳参数均带入客户端时间+△timestamp，即发送请求时的服务端的当前时间</li>
<li>客户端生成仅一次有效的随机字符串nonce_client（防止60s内的攻击）</li>
<li>客户端读取uid（uid由服务端生成，并与用户会话相关，后续完整性校验以及敏感信息传输中均使用到该uid，uid的生成和传输过程详见<a href="#uid%E7%9A%84%E7%94%9F%E6%88%90%E5%92%8C%E4%BC%A0%E8%BE%93%E6%96%B9%E6%A1%88">uid的生成和传输方案</a>）</li>
<li>客户端调用签名算法，<code>sign_client=hash(timestamp+nonce_client+uid)</code>，sign_client、timestamp、nonce_client三个参数（一般放到自定义header中）随请求发送到服务端（做签名计算是为了防止nonce和timestamp被篡改，uid字段不随请求发送防止中间人劫持）</li>
<li>服务端收到请求后，读取参数值timestamp、nonce_client、sign_client,并对这三个参数做非空判断，若不为空则进行步骤7</li>
<li>验证timestamp参数，服务端当前时间timestamp_now-timestamp是否大于60s或&lt;-5s（默认一次HTTP请求从发出到到达服务器的时间是不会超过60s的，且不会小于0，考虑到计算机精度和多网关业务场景，故判断条件为&gt;60s或&lt;-5s）。若大于60s或&lt;-5s，则请求无效；反之为有效请求，则进行步骤8</li>
<li>验证nonce_client参数，nonce_client在服务端缓存中是否存在，如果存在则请求无效，视为重放攻击；若不存在则进行步骤9，并将nonce_client记录在服务端缓存中，失效时间一般设置为60s</li>
<li>验证sign_client参数，服务端根据请求的会话标识读取该用户的uid参数，并记录前端传回的timestamp、nonce_client参数，调用签名生成算法，得到<code>sign_server=hash（timestamp+nonce_client+uid）</code>，验证sign_server是否等于sign_client，若一致，说明参数未被篡改，请求有效，进行请求业务处理流程；若不一致，说明参数被篡改，将请求丢弃。</li>
</ol>
<p>防重放机制图示<br><img src="/blog/images/%E9%98%B2%E9%87%8D%E6%94%BE%E6%9C%BA%E5%88%B6%E5%9B%BE.png"></p>
<p><strong>代码实现</strong></p>
<pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token comment">// Spring拦截器实现</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Enumeration</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Objects</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span>concurrent<span class="token punctuation">.</span></span><span class="token class-name">TimeUnit</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">com<span class="token punctuation">.</span>google<span class="token punctuation">.</span>common<span class="token punctuation">.</span>cache<span class="token punctuation">.</span></span><span class="token operator">*</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>http<span class="token punctuation">.</span></span><span class="token class-name">HttpServletRequest</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>http<span class="token punctuation">.</span></span><span class="token class-name">HttpServletResponse</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>bouncycastle<span class="token punctuation">.</span>crypto<span class="token punctuation">.</span>digests<span class="token punctuation">.</span></span><span class="token class-name">SM3Digest</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>bouncycastle<span class="token punctuation">.</span>util<span class="token punctuation">.</span>encoders<span class="token punctuation">.</span></span><span class="token class-name">Hex</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>web<span class="token punctuation">.</span>method<span class="token punctuation">.</span></span><span class="token class-name">HandlerMethod</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>web<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>handler<span class="token punctuation">.</span></span><span class="token class-name">HandlerInterceptorAdapter</span></span><span class="token punctuation">;</span>

<span class="token comment">/**
 * 重放攻击漏洞
 */</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ReplayAttackInterceptor</span> <span class="token keyword">extends</span> <span class="token class-name">HandlerInterceptorAdapter</span> <span class="token punctuation">&#123;</span>
	<span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">preHandle</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> request<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> response<span class="token punctuation">,</span> <span class="token class-name">Object</span> handler<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">&#123;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>handler <span class="token keyword">instanceof</span> <span class="token class-name">HandlerMethod</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>	  
<span class="token comment">//            HandlerMethod handlerMethod = (HandlerMethod) handler;</span>
			<span class="token comment">// 白名单</span>
			<span class="token class-name">String</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> white <span class="token operator">=</span><span class="token punctuation">&#123;</span><span class="token string">"/update"</span><span class="token punctuation">,</span><span class="token string">"/add"</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
			<span class="token class-name">Enumeration</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">></span></span> names <span class="token operator">=</span> request<span class="token punctuation">.</span><span class="token function">getParameterNames</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token class-name">String</span> path <span class="token operator">=</span>request<span class="token punctuation">.</span><span class="token function">getServletPath</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> white<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
				<span class="token keyword">if</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span>white<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">!=</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>

					<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
				<span class="token punctuation">&#125;</span>
			<span class="token punctuation">&#125;</span>
            <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token string">"GET"</span><span class="token punctuation">.</span><span class="token function">equalsIgnoreCase</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span><span class="token function">getMethod</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
            	<span class="token comment">//客户端时间+△timestamp，即发送请求时的服务端的当前时间</span>
    			<span class="token class-name">Long</span> timestamp <span class="token operator">=</span> <span class="token class-name">Long</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span><span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token string">"timestamp"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    			<span class="token comment">// 客户端生成的仅一次有效的随机字符串</span>
    			<span class="token class-name">String</span> nonce_client <span class="token operator">=</span> request<span class="token punctuation">.</span><span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token string">"nonce_client"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    			<span class="token comment">// 客户端签名算法</span>
    			<span class="token class-name">String</span> sign_client <span class="token operator">=</span> request<span class="token punctuation">.</span><span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token string">"sign_client"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    			
    			<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token class-name">Objects</span><span class="token punctuation">.</span><span class="token function">nonNull</span><span class="token punctuation">(</span>timestamp<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token class-name">Objects</span><span class="token punctuation">.</span><span class="token function">nonNull</span><span class="token punctuation">(</span>nonce_client<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token class-name">Objects</span><span class="token punctuation">.</span><span class="token function">nonNull</span><span class="token punctuation">(</span>sign_client<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    				<span class="token comment">// 失效时间</span>
                	<span class="token keyword">int</span> seconds <span class="token operator">=</span> <span class="token number">60</span><span class="token punctuation">;</span>
                	<span class="token comment">// 服务器当前时间</span>
                	<span class="token keyword">long</span> currentTime <span class="token operator">=</span> <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">currentTimeMillis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                	<span class="token keyword">long</span> timeDiff <span class="token operator">=</span> currentTime <span class="token operator">-</span> timestamp<span class="token punctuation">;</span>
                	<span class="token comment">// 默认一次HTTP请求从发出到到达服务器的时间是不会超过60s的，且不会小于0，考虑到计算机精度和多网关业务场景，故判断条件为>60s或&lt;-5s</span>
                	<span class="token keyword">if</span><span class="token punctuation">(</span>timeDiff <span class="token operator">></span> seconds<span class="token operator">*</span><span class="token number">1000</span> <span class="token operator">||</span> timeDiff <span class="token operator">&lt;</span> <span class="token operator">-</span><span class="token number">5</span><span class="token operator">*</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                		<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
                	<span class="token punctuation">&#125;</span>
                	<span class="token comment">// 验证nonce_client参数</span>
                	<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token class-name">Objects</span><span class="token punctuation">.</span><span class="token function">nonNull</span><span class="token punctuation">(</span><span class="token class-name">GuavaCache</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>nonce_client<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                		<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
                	<span class="token punctuation">&#125;</span>
                	<span class="token class-name">GuavaCache</span><span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>nonce_client<span class="token punctuation">,</span> nonce_client<span class="token punctuation">)</span><span class="token punctuation">;</span>
                	<span class="token comment">// 验证sign_client参数</span>
                	<span class="token comment">// 服务端根据请求的会话标识读取该用户的uid参数</span>
                	<span class="token class-name">String</span> uid <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">)</span>request<span class="token punctuation">.</span><span class="token function">getSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">"uid"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                	<span class="token comment">// 调用签名算法sign_server=hash（timestamp+nonce_client+uid）</span>
                	<span class="token class-name">String</span> sign_server <span class="token operator">=</span> <span class="token function">generateSM3HASH</span><span class="token punctuation">(</span>timestamp<span class="token operator">+</span>nonce_client<span class="token operator">+</span>uid<span class="token punctuation">)</span><span class="token punctuation">;</span>
                	
                	<span class="token keyword">if</span><span class="token punctuation">(</span>sign_server<span class="token punctuation">.</span><span class="token function">equalsIgnoreCase</span><span class="token punctuation">(</span>sign_client<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                		<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
                	<span class="token punctuation">&#125;</span>
    			<span class="token punctuation">&#125;</span>
    			<span class="token comment">// StringBuffer url = request.getRequestURL();</span>
    			<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>   
            <span class="token punctuation">&#125;</span>
        	<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
            
        <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">preHandle</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> response<span class="token punctuation">,</span> handler<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
	<span class="token punctuation">&#125;</span>
	<span class="token comment">//摘要计算</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">generateSM3HASH</span><span class="token punctuation">(</span><span class="token class-name">String</span> src<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> md <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token number">32</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> msg1 <span class="token operator">=</span> src<span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">//System.out.println(Util.byteToHex(msg1));</span>
        <span class="token class-name">SM3Digest</span> sm3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM3Digest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        sm3<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>msg1<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> msg1<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
        sm3<span class="token punctuation">.</span><span class="token function">doFinal</span><span class="token punctuation">(</span>md<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> s <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token class-name">Hex</span><span class="token punctuation">.</span><span class="token function">encode</span><span class="token punctuation">(</span>md<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> s<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">GuavaCache</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// 缓存项最大数量</span>
        <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> <span class="token constant">GUAVA_CACHE_SIZE</span> <span class="token operator">=</span> <span class="token number">100000</span><span class="token punctuation">;</span>
        <span class="token comment">// 缓存时间(秒)</span>
        <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> <span class="token constant">GUAVA_CACHE_SECONDS</span> <span class="token operator">=</span> <span class="token number">60</span><span class="token punctuation">;</span>
        <span class="token comment">// 缓存操作对象</span>
        <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">LoadingCache</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">></span></span> <span class="token constant">GLOBAL_CACHE</span> <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        
        <span class="token keyword">static</span> <span class="token punctuation">&#123;</span>
            <span class="token constant">GLOBAL_CACHE</span> <span class="token operator">=</span> <span class="token function">loadCache</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">CacheLoader</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                <span class="token annotation punctuation">@Override</span>
                <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">load</span><span class="token punctuation">(</span><span class="token class-name">String</span> key<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                    <span class="token comment">// get键 值不存在时，加载新值到该键中</span>
                    <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
                <span class="token punctuation">&#125;</span>
            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        
        <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">LoadingCache</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">></span></span> <span class="token function">loadCache</span><span class="token punctuation">(</span><span class="token class-name">CaceLoader</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">></span></span> cacheLoader<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token class-name">LoadingCache</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">></span></span> cache <span class="token operator">=</span> <span class="token class-name">CacheBuilder</span><span class="token punctuation">.</span><span class="token function">newBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">maxmumSize</span><span class="token punctuation">(</span><span class="token constant">GUAVA_CACHE_SIZE</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">expireAfterAccess</span><span class="token punctuation">(</span><span class="token constant">GUAVA_CACHE_SECONDS</span><span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span><span class="token constant">SECONDS</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">expireAfterWrite</span><span class="token punctuation">(</span><span class="token constant">GUAVA_CACHE_SECONDS</span><span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span><span class="token constant">SECONDS</span><span class="token punctuation">)</span>
                <span class="token comment">// 移除缓存</span>
                <span class="token punctuation">.</span><span class="token function">removalListener</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">RemovalListener</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                    <span class="token annotation punctuation">@Override</span>
                    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onRemoval</span><span class="token punctuation">(</span><span class="token class-name">RemovalNotification</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">></span></span> arg0<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                        <span class="token comment">// 相关逻辑</span>
                    <span class="token punctuation">&#125;</span>
                <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">recordStats</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span>cacheLoader<span class="token punctuation">)</span><span class="token punctuation">;</span>
            
            <span class="token keyword">return</span> cache<span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        
        <span class="token comment">/**
         * 添加缓存
         */</span>
        <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token class-name">String</span> key<span class="token punctuation">,</span> <span class="token class-name">Object</span> value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token constant">GLOBAL_CACHE</span><span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> 
        
        <span class="token comment">/**
         * 当get键值不存在时，加载CacheLoader load()方法 加载新值到改键中 当return null 时会抛异常
         */</span>
        <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">Object</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token class-name">String</span> key<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">try</span><span class="token punctuation">&#123;</span>
                <span class="token keyword">return</span> <span class="token constant">GLOBAL_CACHE</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span><span class="token keyword">catch</span><span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h2 id="uid的生成和传输方案"><a href="#uid的生成和传输方案" class="headerlink" title="uid的生成和传输方案"></a>uid的生成和传输方案</h2><p><strong>uid的使用场景</strong></p>
<p>uid作为重放攻击解决方案中计算签名的盐值、也是完整性校验中计算签名的盐值，同时也是用作对称加密的密钥（敏感数据加密传输），因此uid的生成和访问机制尤为重要。<br>本方案综合考虑了uid的传输安全、防止中间人劫持，可保证每个用户每个会话周期内的uid均不同，且无法伪造。</p>
<ol>
<li>用户首次访问系统后，请求服务端公钥（非对称加密算法生成的公私钥）</li>
<li>服务端生成与用户会话相关的公私钥对（会话周期内有效），将公钥publickey_server发送给客户端（为防止攻击者分析并收集加固信息，服务端公钥随其他响应信息一起传回客户端，不单独发送）</li>
<li>客户端接收响应后将publickey_server存储到localstorage中（加固相关信息存储到localstorage中而不是sessionstorage中，是为了防止客户端浏览器跨页面操作时获取不到相关参数）</li>
<li>客户端生成公私钥对，用服务端公钥对客户端公钥进行加密<code>encryptpublickey_client=SM2.encrypt(publickey_client，publickey_server)</code>，并将加密后的客户端公钥发送到服务端</li>
<li>服务端接收请求后使用服务端私钥对其解密，获取明文客户端公钥<code>publickey_client=SM2.decrypt(encryptpublickey_client，privatekey_server)</code></li>
<li>服务端生成与用户会话相关的随机数uid（会话周期有效），并使用客户端公钥对uid进行加密后发送到客户端，<code>encryptuid=SM2.encrypt(uid，publickey_client)</code></li>
<li>客户端接收响应数据后，用客户端私钥对其进行解密得到明文uid，<code>uid=SM2.decrypt(encryptuid，privatekey_client)</code>，并将uid本地localstorage中保存待后续使用。</li>
</ol>
<p>注意：若系统使用SSL机制，则服务端生成uid后可直接返回给客户端，无需进行手动加解密过程。</p>
<p>详见下图所示<br><img src="/blog/images/uid%E7%9A%84%E7%94%9F%E6%88%90%E5%92%8C%E4%BC%A0%E8%BE%93%E6%96%B9%E6%A1%88.png"></p>
<p>简明扼要前后端登录国密加解密:</p>
<ol>
<li>服务端根据用户会话生成密钥对</li>
<li>客户端获取服务端公钥，保存至localStorage</li>
<li>客户端生成密钥对，通过服务端公钥加密客户端公钥然后发送到服务端。</li>
<li>服务端通过服务端私钥解密获取客户端公钥</li>
<li>服务端生成uid(数据完整性校验、防重返时使用)，通过客户端公钥加密uid返回给客户端</li>
<li>客户端通过客户端私钥解密uid，进行放重放、完整性校验使用。</li>
</ol>
<p><strong>代码实现</strong></p>
<pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token comment">// 适配sm-crypto的SM2Util.java</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>bouncycastle<span class="token punctuation">.</span>crypto<span class="token punctuation">.</span>engines<span class="token punctuation">.</span></span><span class="token class-name">SM2Engine</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>bouncycastle<span class="token punctuation">.</span>crypto<span class="token punctuation">.</span>params<span class="token punctuation">.</span></span><span class="token class-name">ECPrivateKeyParameters</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>bouncycastle<span class="token punctuation">.</span>crypto<span class="token punctuation">.</span>params<span class="token punctuation">.</span></span><span class="token class-name">ECPublicKeyParameters</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>bouncycastle<span class="token punctuation">.</span>crypto<span class="token punctuation">.</span>params<span class="token punctuation">.</span></span><span class="token class-name">ParametersWithRandom</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>bouncycastle<span class="token punctuation">.</span>jce<span class="token punctuation">.</span>provider<span class="token punctuation">.</span></span><span class="token class-name">BouncyCastleProvider</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>bouncycastle<span class="token punctuation">.</span>crypto<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">PrivateKeyFactory</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>bouncycastle<span class="token punctuation">.</span>crypto<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">PublicKeyFactory</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>bouncycastle<span class="token punctuation">.</span>util<span class="token punctuation">.</span>encoders<span class="token punctuation">.</span></span><span class="token class-name">Hex</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>nio<span class="token punctuation">.</span>charset<span class="token punctuation">.</span></span><span class="token class-name">StandardCharsets</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span></span><span class="token operator">*</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span><span class="token class-name">PKCS8EncodedKeySpec</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span><span class="token class-name">X509EncodedKeySpec</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Arrays</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Base64</span></span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SM2Util</span> <span class="token punctuation">&#123;</span>

    <span class="token keyword">static</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name">Security</span><span class="token punctuation">.</span><span class="token function">addProvider</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">BouncyCastleProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 获取密钥对
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">KeyPair</span> <span class="token function">generateSM2KeyPair</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name">KeyPairGenerator</span> keyGen <span class="token operator">=</span> <span class="token class-name">KeyPairGenerator</span><span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token string">"EC"</span><span class="token punctuation">,</span> <span class="token string">"BC"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        keyGen<span class="token punctuation">.</span><span class="token function">initialize</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span>ECGenParameterSpec</span><span class="token punctuation">(</span><span class="token string">"sm2p256v1"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> keyGen<span class="token punctuation">.</span><span class="token function">generateKeyPair</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token comment">/**
     * 获取未压缩公钥Hex（供前端使用）
     * 当需要将公钥发送给前端使用时调用此方法
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">getUncompressedPubKeyHex</span><span class="token punctuation">(</span><span class="token class-name">PublicKey</span> pubKey<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>interfaces<span class="token punctuation">.</span></span>ECPublicKey</span> ecPub <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>interfaces<span class="token punctuation">.</span></span>ECPublicKey</span><span class="token punctuation">)</span> pubKey<span class="token punctuation">;</span>
        <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span>ECPoint</span> w <span class="token operator">=</span> ecPub<span class="token punctuation">.</span><span class="token function">getW</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token string">"04"</span>
                <span class="token operator">+</span> <span class="token function">paddedHex</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span><span class="token function">getAffineX</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toByteArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token operator">+</span> <span class="token function">paddedHex</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span><span class="token function">getAffineY</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toByteArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">paddedHex</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> bytes<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name">String</span> s <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>math<span class="token punctuation">.</span></span>BigInteger</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> bytes<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token number">16</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">while</span> <span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&lt;</span> <span class="token number">64</span><span class="token punctuation">)</span> s <span class="token operator">=</span> <span class="token string">"0"</span> <span class="token operator">+</span> s<span class="token punctuation">;</span>
        <span class="token keyword">return</span> s<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 获取私钥的PKCS#8 DER编码（Base64）—— 可直接硬编码复用
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">getPrivateKeyPkcs8Base64</span><span class="token punctuation">(</span><span class="token class-name">PrivateKey</span> privateKey<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token class-name">Base64</span><span class="token punctuation">.</span><span class="token function">getEncoder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">encodeToString</span><span class="token punctuation">(</span>privateKey<span class="token punctuation">.</span><span class="token function">getEncoded</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 从前端公钥Hex字符串加载公钥
     * 获取前端公钥加密数据调用此方法
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">PublicKey</span> <span class="token function">loadPublicKeyFromHex</span><span class="token punctuation">(</span><span class="token class-name">String</span> publicKeyHex<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> publicKeyBytes <span class="token operator">=</span> <span class="token class-name">Hex</span><span class="token punctuation">.</span><span class="token function">decode</span><span class="token punctuation">(</span>publicKeyHex<span class="token punctuation">)</span><span class="token punctuation">;</span>
        
        <span class="token comment">// 如果是04开头的未压缩格式，直接使用</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>publicKeyBytes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token number">0x04</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token comment">// 使用X509编码格式</span>
            <span class="token class-name">String</span> x509Base64 <span class="token operator">=</span> <span class="token function">getX509PublicKeyBase64</span><span class="token punctuation">(</span>publicKeyBytes<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token function">loadPublicKeyFromBase64</span><span class="token punctuation">(</span>x509Base64<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        
        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span><span class="token punctuation">(</span><span class="token string">"不支持的公钥格式"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 将未压缩公钥转换为X509格式
     */</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">getX509PublicKeyBase64</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> uncompressedPublicKey<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// 这里需要将未压缩公钥转换为X509格式</span>
        <span class="token comment">// 简化处理：直接使用BouncyCastle的KeyFactory</span>
        <span class="token class-name">KeyFactory</span> keyFactory <span class="token operator">=</span> <span class="token class-name">KeyFactory</span><span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token string">"EC"</span><span class="token punctuation">,</span> <span class="token string">"BC"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span>ECPoint</span> point <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span>ECPoint</span><span class="token punctuation">(</span>
            <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>math<span class="token punctuation">.</span></span>BigInteger</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token class-name">Arrays</span><span class="token punctuation">.</span><span class="token function">copyOfRange</span><span class="token punctuation">(</span>uncompressedPublicKey<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">33</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
            <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>math<span class="token punctuation">.</span></span>BigInteger</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token class-name">Arrays</span><span class="token punctuation">.</span><span class="token function">copyOfRange</span><span class="token punctuation">(</span>uncompressedPublicKey<span class="token punctuation">,</span> <span class="token number">33</span><span class="token punctuation">,</span> <span class="token number">65</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span>ECParameterSpec</span> ecSpec <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span>ECParameterSpec</span><span class="token punctuation">(</span>
            <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span>EllipticCurve</span><span class="token punctuation">(</span>
                <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span>ECFieldFp</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>math<span class="token punctuation">.</span></span>BigInteger</span><span class="token punctuation">(</span><span class="token string">"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"</span><span class="token punctuation">,</span> <span class="token number">16</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
                <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>math<span class="token punctuation">.</span></span>BigInteger</span><span class="token punctuation">(</span><span class="token string">"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC"</span><span class="token punctuation">,</span> <span class="token number">16</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
                <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>math<span class="token punctuation">.</span></span>BigInteger</span><span class="token punctuation">(</span><span class="token string">"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93"</span><span class="token punctuation">,</span> <span class="token number">16</span><span class="token punctuation">)</span>
            <span class="token punctuation">)</span><span class="token punctuation">,</span>
            <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span>ECPoint</span><span class="token punctuation">(</span>
                <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>math<span class="token punctuation">.</span></span>BigInteger</span><span class="token punctuation">(</span><span class="token string">"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"</span><span class="token punctuation">,</span> <span class="token number">16</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
                <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>math<span class="token punctuation">.</span></span>BigInteger</span><span class="token punctuation">(</span><span class="token string">"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"</span><span class="token punctuation">,</span> <span class="token number">16</span><span class="token punctuation">)</span>
            <span class="token punctuation">)</span><span class="token punctuation">,</span>
            <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>math<span class="token punctuation">.</span></span>BigInteger</span><span class="token punctuation">(</span><span class="token string">"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"</span><span class="token punctuation">,</span> <span class="token number">16</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
            <span class="token number">1</span>
        <span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span>ECPublicKeySpec</span> pubKeySpec <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>security<span class="token punctuation">.</span>spec<span class="token punctuation">.</span></span>ECPublicKeySpec</span><span class="token punctuation">(</span>point<span class="token punctuation">,</span> ecSpec<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token class-name">Base64</span><span class="token punctuation">.</span><span class="token function">getEncoder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">encodeToString</span><span class="token punctuation">(</span>keyFactory<span class="token punctuation">.</span><span class="token function">generatePublic</span><span class="token punctuation">(</span>pubKeySpec<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getEncoded</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 从Base64加载公钥
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">PublicKey</span> <span class="token function">loadPublicKeyFromBase64</span><span class="token punctuation">(</span><span class="token class-name">String</span> x509Base64<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> x509 <span class="token operator">=</span> <span class="token class-name">Base64</span><span class="token punctuation">.</span><span class="token function">getDecoder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">decode</span><span class="token punctuation">(</span>x509Base64<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">X509EncodedKeySpec</span> spec <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">X509EncodedKeySpec</span><span class="token punctuation">(</span>x509<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">KeyFactory</span> keyFactory <span class="token operator">=</span> <span class="token class-name">KeyFactory</span><span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token string">"EC"</span><span class="token punctuation">,</span> <span class="token string">"BC"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> keyFactory<span class="token punctuation">.</span><span class="token function">generatePublic</span><span class="token punctuation">(</span>spec<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 使用前端公钥加密（返回C1C3C2格式Hex字符串，与前端sm-crypto兼容）
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">encryptForFrontend</span><span class="token punctuation">(</span><span class="token class-name">String</span> plainText<span class="token punctuation">,</span> <span class="token class-name">PublicKey</span> publicKey<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// 创建公钥参数</span>
        <span class="token class-name">ECPublicKeyParameters</span> pubKeyParam <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">ECPublicKeyParameters</span><span class="token punctuation">)</span>
                <span class="token class-name">PublicKeyFactory</span><span class="token punctuation">.</span><span class="token function">createKey</span><span class="token punctuation">(</span>publicKey<span class="token punctuation">.</span><span class="token function">getEncoded</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 加密必须使用ParametersWithRandom</span>
        <span class="token class-name">SecureRandom</span> random <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SecureRandom</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">ParametersWithRandom</span> params <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ParametersWithRandom</span><span class="token punctuation">(</span>pubKeyParam<span class="token punctuation">,</span>random<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 使用C1C2C3模式加密</span>
        <span class="token class-name">SM2Engine</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM2Engine</span><span class="token punctuation">(</span><span class="token class-name">SM2Engine<span class="token punctuation">.</span>Mode</span><span class="token punctuation">.</span><span class="token constant">C1C2C3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        engine<span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> params<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> plainBytes <span class="token operator">=</span> plainText<span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation">.</span><span class="token constant">UTF_8</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> cipherBytes <span class="token operator">=</span> engine<span class="token punctuation">.</span><span class="token function">processBlock</span><span class="token punctuation">(</span>plainBytes<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> plainBytes<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 转换为C1C3C2格式（前端期望的格式）</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c1c3c2 <span class="token operator">=</span> <span class="token function">convertC1C2C3ToC1C3C2</span><span class="token punctuation">(</span>cipherBytes<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token class-name">Hex</span><span class="token punctuation">.</span><span class="token function">toHexString</span><span class="token punctuation">(</span>c1c3c2<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 使用服务端私钥解密前端发来的使用服务端公钥加密的数据
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">decryptFromFrontend</span><span class="token punctuation">(</span><span class="token class-name">String</span> encryptedHex<span class="token punctuation">,</span> <span class="token class-name">PrivateKey</span> privateKey<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> cipherBytes <span class="token operator">=</span> <span class="token class-name">Hex</span><span class="token punctuation">.</span><span class="token function">decode</span><span class="token punctuation">(</span>encryptedHex<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 根据第一个字节判断格式</span>
        <span class="token keyword">int</span> firstByte <span class="token operator">=</span> cipherBytes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">&amp;</span> <span class="token number">0xFF</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span>firstByte <span class="token operator">==</span> <span class="token number">0x04</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"检测到未压缩格式 (04开头) - 使用C1C3C2转C1C2C3"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token function">decryptC1C3C2</span><span class="token punctuation">(</span>cipherBytes<span class="token punctuation">,</span> privateKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>firstByte <span class="token operator">==</span> <span class="token number">0x02</span> <span class="token operator">||</span> firstByte <span class="token operator">==</span> <span class="token number">0x03</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"检测到压缩格式 ("</span> <span class="token operator">+</span> <span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"%02x"</span><span class="token punctuation">,</span> firstByte<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">"开头) - 直接解密"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token function">decryptCompressed</span><span class="token punctuation">(</span>cipherBytes<span class="token punctuation">,</span> privateKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"检测到未知格式，尝试自动处理"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token function">tryAllFormats</span><span class="token punctuation">(</span>cipherBytes<span class="token punctuation">,</span> privateKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * C1C3C2 → C1C2C3 转换
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">convertC1C3C2ToC1C2C3</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c1c3c2<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">int</span> c1Len <span class="token operator">=</span> <span class="token number">65</span><span class="token punctuation">;</span> <span class="token comment">// 未压缩点：0x04 + 32x + 32y</span>
        <span class="token keyword">int</span> c3Len <span class="token operator">=</span> <span class="token number">32</span><span class="token punctuation">;</span> <span class="token comment">// SM3 digest (32字节)</span>
        <span class="token keyword">int</span> totalLen <span class="token operator">=</span> c1c3c2<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
        <span class="token keyword">int</span> c2Len <span class="token operator">=</span> totalLen <span class="token operator">-</span> c1Len <span class="token operator">-</span> c3Len<span class="token punctuation">;</span>

        <span class="token comment">// 验证长度</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>totalLen <span class="token operator">&lt;</span> c1Len <span class="token operator">+</span> c3Len<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span><span class="token punctuation">(</span><span class="token string">"密文长度无效: "</span> <span class="token operator">+</span> totalLen <span class="token operator">+</span> <span class="token string">"，至少需要 "</span> <span class="token operator">+</span> <span class="token punctuation">(</span>c1Len <span class="token operator">+</span> c3Len<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">" 字节"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>

        <span class="token comment">// System.out.println("C1C3C2转换详情:");</span>
        <span class="token comment">// System.out.println("  - 总长度: " + totalLen);</span>
        <span class="token comment">// System.out.println("  - C1长度: " + c1Len);</span>
        <span class="token comment">// System.out.println("  - C3长度: " + c3Len);</span>
        <span class="token comment">// System.out.println("  - C2长度: " + c2Len);</span>

        <span class="token comment">// 分割各部分</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c1 <span class="token operator">=</span> <span class="token class-name">Arrays</span><span class="token punctuation">.</span><span class="token function">copyOfRange</span><span class="token punctuation">(</span>c1c3c2<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> c1Len<span class="token punctuation">)</span><span class="token punctuation">;</span>           <span class="token comment">// 公钥点</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c3 <span class="token operator">=</span> <span class="token class-name">Arrays</span><span class="token punctuation">.</span><span class="token function">copyOfRange</span><span class="token punctuation">(</span>c1c3c2<span class="token punctuation">,</span> c1Len<span class="token punctuation">,</span> c1Len <span class="token operator">+</span> c3Len<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// SM3哈希</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c2 <span class="token operator">=</span> <span class="token class-name">Arrays</span><span class="token punctuation">.</span><span class="token function">copyOfRange</span><span class="token punctuation">(</span>c1c3c2<span class="token punctuation">,</span> c1Len <span class="token operator">+</span> c3Len<span class="token punctuation">,</span> totalLen<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 实际加密数据</span>

        <span class="token comment">// 重组为 C1C2C3</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c1c2c3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">byte</span><span class="token punctuation">[</span>totalLen<span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">arraycopy</span><span class="token punctuation">(</span>c1<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> c1c2c3<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> c1Len<span class="token punctuation">)</span><span class="token punctuation">;</span>           <span class="token comment">// C1</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">arraycopy</span><span class="token punctuation">(</span>c2<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> c1c2c3<span class="token punctuation">,</span> c1Len<span class="token punctuation">,</span> c2Len<span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token comment">// C2</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">arraycopy</span><span class="token punctuation">(</span>c3<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> c1c2c3<span class="token punctuation">,</span> c1Len <span class="token operator">+</span> c2Len<span class="token punctuation">,</span> c3Len<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// C3</span>

        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"C1C3C2 → C1C2C3 转换完成"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> c1c2c3<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 反向转换：C1C2C3 → C1C3C2
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">convertC1C2C3ToC1C3C2</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c1c2c3<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">int</span> c1Len <span class="token operator">=</span> <span class="token number">65</span><span class="token punctuation">;</span> <span class="token comment">// 未压缩点</span>
        <span class="token keyword">int</span> c3Len <span class="token operator">=</span> <span class="token number">32</span><span class="token punctuation">;</span> <span class="token comment">// SM3 digest</span>
        <span class="token keyword">int</span> totalLen <span class="token operator">=</span> c1c2c3<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
        <span class="token keyword">int</span> c2Len <span class="token operator">=</span> totalLen <span class="token operator">-</span> c1Len <span class="token operator">-</span> c3Len<span class="token punctuation">;</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span>totalLen <span class="token operator">&lt;</span> c1Len <span class="token operator">+</span> c3Len<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span><span class="token punctuation">(</span><span class="token string">"密文长度无效: "</span> <span class="token operator">+</span> totalLen<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>

        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c1 <span class="token operator">=</span> <span class="token class-name">Arrays</span><span class="token punctuation">.</span><span class="token function">copyOfRange</span><span class="token punctuation">(</span>c1c2c3<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> c1Len<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c2 <span class="token operator">=</span> <span class="token class-name">Arrays</span><span class="token punctuation">.</span><span class="token function">copyOfRange</span><span class="token punctuation">(</span>c1c2c3<span class="token punctuation">,</span> c1Len<span class="token punctuation">,</span> c1Len <span class="token operator">+</span> c2Len<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c3 <span class="token operator">=</span> <span class="token class-name">Arrays</span><span class="token punctuation">.</span><span class="token function">copyOfRange</span><span class="token punctuation">(</span>c1c2c3<span class="token punctuation">,</span> c1Len <span class="token operator">+</span> c2Len<span class="token punctuation">,</span> totalLen<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c1c3c2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">byte</span><span class="token punctuation">[</span>totalLen<span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">arraycopy</span><span class="token punctuation">(</span>c1<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> c1c3c2<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> c1Len<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">arraycopy</span><span class="token punctuation">(</span>c3<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> c1c3c2<span class="token punctuation">,</span> c1Len<span class="token punctuation">,</span> c3Len<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">arraycopy</span><span class="token punctuation">(</span>c2<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> c1c3c2<span class="token punctuation">,</span> c1Len <span class="token operator">+</span> c3Len<span class="token punctuation">,</span> c2Len<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">return</span> c1c3c2<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 未压缩格式解密（04开头）
     */</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">decryptC1C3C2</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> cipherBytes<span class="token punctuation">,</span> <span class="token class-name">PrivateKey</span> privateKey<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// C1C3C2 → C1C2C3</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> c1c2c3 <span class="token operator">=</span> <span class="token function">convertC1C3C2ToC1C2C3</span><span class="token punctuation">(</span>cipherBytes<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token class-name">ECPrivateKeyParameters</span> privKeyParam <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">ECPrivateKeyParameters</span><span class="token punctuation">)</span>
                <span class="token class-name">PrivateKeyFactory</span><span class="token punctuation">.</span><span class="token function">createKey</span><span class="token punctuation">(</span>privateKey<span class="token punctuation">.</span><span class="token function">getEncoded</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 使用C1C2C3模式解密</span>
        <span class="token class-name">SM2Engine</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM2Engine</span><span class="token punctuation">(</span><span class="token class-name">SM2Engine<span class="token punctuation">.</span>Mode</span><span class="token punctuation">.</span><span class="token constant">C1C2C3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        engine<span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> privKeyParam<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> plainBytes <span class="token operator">=</span> engine<span class="token punctuation">.</span><span class="token function">processBlock</span><span class="token punctuation">(</span>c1c2c3<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> c1c2c3<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span>plainBytes<span class="token punctuation">,</span> <span class="token class-name">StandardCharsets</span><span class="token punctuation">.</span><span class="token constant">UTF_8</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 压缩格式解密（02或03开头）
     */</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">decryptCompressed</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> cipherBytes<span class="token punctuation">,</span> <span class="token class-name">PrivateKey</span> privateKey<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name">ECPrivateKeyParameters</span> privKeyParam <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">ECPrivateKeyParameters</span><span class="token punctuation">)</span> <span class="token class-name">PrivateKeyFactory</span><span class="token punctuation">.</span><span class="token function">createKey</span><span class="token punctuation">(</span>privateKey<span class="token punctuation">.</span><span class="token function">getEncoded</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 压缩格式通常直接使用C1C2C3模式</span>
        <span class="token class-name">SM2Engine</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM2Engine</span><span class="token punctuation">(</span><span class="token class-name">SM2Engine<span class="token punctuation">.</span>Mode</span><span class="token punctuation">.</span><span class="token constant">C1C2C3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        engine<span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> privKeyParam<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> plainBytes <span class="token operator">=</span> engine<span class="token punctuation">.</span><span class="token function">processBlock</span><span class="token punctuation">(</span>cipherBytes<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> cipherBytes<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span>plainBytes<span class="token punctuation">,</span> <span class="token class-name">StandardCharsets</span><span class="token punctuation">.</span><span class="token constant">UTF_8</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">// 尝试所有可能的格式</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">tryAllFormats</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> cipherBytes<span class="token punctuation">,</span> <span class="token class-name">PrivateKey</span> privateKey<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// 原有的尝试逻辑</span>
        <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> methods <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
                <span class="token string">"原始数据(C1C2C3)"</span><span class="token punctuation">,</span>
                <span class="token string">"原始数据(C1C3C2)"</span><span class="token punctuation">,</span>
                <span class="token string">"添加04前缀(C1C2C3)"</span><span class="token punctuation">,</span>
                <span class="token string">"添加04前缀并转C1C2C3"</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> testData <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
                cipherBytes<span class="token punctuation">,</span> <span class="token comment">// 原始</span>
                cipherBytes<span class="token punctuation">,</span> <span class="token comment">// 原始（不同模式）</span>
                <span class="token function">addPrefix</span><span class="token punctuation">(</span>cipherBytes<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">)</span> <span class="token number">0x04</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// 加04</span>
                <span class="token function">convertC1C3C2ToC1C2C3</span><span class="token punctuation">(</span><span class="token function">addPrefix</span><span class="token punctuation">(</span>cipherBytes<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">)</span> <span class="token number">0x04</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 加04并转换</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

        <span class="token class-name">SM2Engine<span class="token punctuation">.</span>Mode</span><span class="token punctuation">[</span><span class="token punctuation">]</span> modes <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
                <span class="token class-name">SM2Engine<span class="token punctuation">.</span>Mode</span><span class="token punctuation">.</span><span class="token constant">C1C2C3</span><span class="token punctuation">,</span>
                <span class="token class-name">SM2Engine<span class="token punctuation">.</span>Mode</span><span class="token punctuation">.</span><span class="token constant">C1C3C2</span><span class="token punctuation">,</span>
                <span class="token class-name">SM2Engine<span class="token punctuation">.</span>Mode</span><span class="token punctuation">.</span><span class="token constant">C1C2C3</span><span class="token punctuation">,</span>
                <span class="token class-name">SM2Engine<span class="token punctuation">.</span>Mode</span><span class="token punctuation">.</span><span class="token constant">C1C2C3</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> methods<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">try</span> <span class="token punctuation">&#123;</span>
                <span class="token class-name">ECPrivateKeyParameters</span> privKeyParam <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">ECPrivateKeyParameters</span><span class="token punctuation">)</span>
                        <span class="token class-name">PrivateKeyFactory</span><span class="token punctuation">.</span><span class="token function">createKey</span><span class="token punctuation">(</span>privateKey<span class="token punctuation">.</span><span class="token function">getEncoded</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

                <span class="token class-name">SM2Engine</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM2Engine</span><span class="token punctuation">(</span>modes<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                engine<span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> privKeyParam<span class="token punctuation">)</span><span class="token punctuation">;</span>

                <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> plainBytes <span class="token operator">=</span> engine<span class="token punctuation">.</span><span class="token function">processBlock</span><span class="token punctuation">(</span>testData<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> testData<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token class-name">String</span> result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span>plainBytes<span class="token punctuation">,</span> <span class="token class-name">StandardCharsets</span><span class="token punctuation">.</span><span class="token constant">UTF_8</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

                <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"✓ "</span> <span class="token operator">+</span> methods<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+</span> <span class="token string">" 解密成功: "</span> <span class="token operator">+</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">return</span> result<span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"✗ "</span> <span class="token operator">+</span> methods<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+</span> <span class="token string">" 失败: "</span> <span class="token operator">+</span> e<span class="token punctuation">.</span><span class="token function">getMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span><span class="token punctuation">(</span><span class="token string">"所有解密尝试都失败"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">addPrefix</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> data<span class="token punctuation">,</span> <span class="token keyword">byte</span> prefix<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">byte</span><span class="token punctuation">[</span>data<span class="token punctuation">.</span>length <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        result<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> prefix<span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">arraycopy</span><span class="token punctuation">(</span>data<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> result<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> data<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> result<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 从Base64加载私钥
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">PrivateKey</span> <span class="token function">loadPrivateKeyFromBase64</span><span class="token punctuation">(</span><span class="token class-name">String</span> pkcs8Base64<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> pkcs8 <span class="token operator">=</span> <span class="token class-name">Base64</span><span class="token punctuation">.</span><span class="token function">getDecoder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">decode</span><span class="token punctuation">(</span>pkcs8Base64<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">PKCS8EncodedKeySpec</span> spec <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PKCS8EncodedKeySpec</span><span class="token punctuation">(</span>pkcs8<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">KeyFactory</span> keyFactory <span class="token operator">=</span> <span class="token class-name">KeyFactory</span><span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token string">"EC"</span><span class="token punctuation">,</span> <span class="token string">"BC"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> keyFactory<span class="token punctuation">.</span><span class="token function">generatePrivate</span><span class="token punctuation">(</span>spec<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 测试方法
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// 服务端生成密钥对</span>
        <span class="token class-name">KeyPair</span> keyPair <span class="token operator">=</span> <span class="token function">generateSM2KeyPair</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 发送前端需要的服务端密钥</span>
        <span class="token class-name">String</span> frontPublicKey <span class="token operator">=</span> <span class="token function">getUncompressedPubKeyHex</span><span class="token punctuation">(</span>keyPair<span class="token punctuation">.</span><span class="token function">getPublic</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 后端私钥转换，易于保存</span>
        <span class="token class-name">String</span> privateKeyBase64 <span class="token operator">=</span> <span class="token function">getPrivateKeyPkcs8Base64</span><span class="token punctuation">(</span>keyPair<span class="token punctuation">.</span><span class="token function">getPrivate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"前端公钥: "</span> <span class="token operator">+</span> frontPublicKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"后端私钥: "</span> <span class="token operator">+</span> privateKeyBase64<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 测试数据</span>
        <span class="token class-name">String</span> encryptedHex <span class="token operator">=</span> <span class="token string">"043aa90069a8ff7a4b4ab45a3a96e2bd6a3d6c0fd12f03d9332cff0c070c6a3baac1914697438318055fc1e72bc558720129d835fd6800c01420fdb83676f2f63cbaa165612f346e859c23b6b1b463bdc3be69406326570ab2df496890bfd55cd5a072cc26eea04bd83f2609a6"</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> privateKeyBase642 <span class="token operator">=</span> <span class="token string">"MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgDSd+qEfDfdciXKEODn9fN5c7CfO6VsHlL765JEnePnmgCgYIKoEcz1UBgi2hRANCAAQFxSaO5eXZtgUKiRq383CDUvanY+7kmvOD/tMTajbOO7nmEqYOij2GWo9uN3mNgus7uy18isn39jQU/SeSBjbr"</span><span class="token punctuation">;</span>

        <span class="token keyword">try</span> <span class="token punctuation">&#123;</span>
            <span class="token class-name">PrivateKey</span> privateKey <span class="token operator">=</span> <span class="token function">loadPrivateKeyFromBase64</span><span class="token punctuation">(</span>privateKeyBase642<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">String</span> decryptedText <span class="token operator">=</span> <span class="token function">decryptFromFrontend</span><span class="token punctuation">(</span>encryptedHex<span class="token punctuation">,</span> privateKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"解密成功! 结果: "</span> <span class="token operator">+</span> decryptedText<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>

        <span class="token comment">// 测试加密解密</span>
        <span class="token class-name">String</span> plainText <span class="token operator">=</span> <span class="token string">"Hello, SM2加密测试!"</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"原始文本: "</span> <span class="token operator">+</span> plainText<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 使用前端公钥加密</span>
        <span class="token class-name">PublicKey</span> publicKey <span class="token operator">=</span> <span class="token function">loadPublicKeyFromHex</span><span class="token punctuation">(</span>frontPublicKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> encrypted <span class="token operator">=</span> <span class="token function">encryptForFrontend</span><span class="token punctuation">(</span>plainText<span class="token punctuation">,</span> publicKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"加密结果: "</span> <span class="token operator">+</span> encrypted<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 使用后端私钥解密</span>
        <span class="token class-name">PrivateKey</span> privateKey <span class="token operator">=</span> <span class="token function">loadPrivateKeyFromBase64</span><span class="token punctuation">(</span>privateKeyBase64<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> decrypted <span class="token operator">=</span> <span class="token function">decryptFromFrontend</span><span class="token punctuation">(</span>encrypted<span class="token punctuation">,</span> privateKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"解密结果: "</span> <span class="token operator">+</span> decrypted<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"加解密验证: "</span> <span class="token operator">+</span> plainText<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>decrypted<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">// &lt;script src="https://cdn.jsdelivr.net/npm/sm-crypto@0.3.2/dist/sm2.min.js">&lt;/script></span>
    <span class="token comment">// let currentPublicKey = "0405c5268ee5e5d9b6050a891ab7f3708352f6a763eee49af383fed3136a36ce3bb9e612a60e8a3d865a8f6e37798d82eb3bbb2d7c8ac9f7f63414fd27920636eb";</span>
    <span class="token comment">// const encryptData = sm2.doEncrypt(plainText, currentPublicKey);</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// smutils.js</span>
<span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">SM4Util</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 和后端key一致</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>secretKey<span class="token operator">=</span><span class="token string">"jjr9bez13evljita"</span><span class="token punctuation">;</span>
    <span class="token comment">// 当时用CBC模式的时候</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>iv <span class="token operator">=</span> <span class="token string">"ZkR_SiNoSOFT=568"</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>hexString <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>

    <span class="token comment">// ECB模式加密</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">encryptData_ECB</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">plainText</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        <span class="token keyword">try</span><span class="token punctuation">&#123;</span>
            <span class="token keyword">const</span> sm4 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM4</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">const</span> ctx <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM4_Context</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            ctx<span class="token punctuation">.</span>isPadding <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
            ctx<span class="token punctuation">.</span>mode <span class="token operator">=</span> sm4<span class="token punctuation">.</span><span class="token constant">SM4_ENCRYPT</span><span class="token punctuation">;</span>
            <span class="token keyword">const</span> keyBytes <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stringToByte</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>secretKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
            sm4<span class="token punctuation">.</span><span class="token function">sm4_setkey_enc</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> keyBytes<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">const</span> encrypted <span class="token operator">=</span> sm4<span class="token punctuation">.</span><span class="token function">sm4_crypt_ecb</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stringToByte</span><span class="token punctuation">(</span>plainText<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">const</span> cipherText <span class="token operator">=</span> base64js<span class="token punctuation">.</span><span class="token function">fromByteArray</span><span class="token punctuation">(</span>encrypted<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>cipherText <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> cipherText<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span>
            <span class="token punctuation">&#123;</span>
                cipherText<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">(\s*|\t|\r|\n)</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
            <span class="token keyword">return</span> cipherText<span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span><span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token comment">//解密_ECB</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">decryptData_ECB</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">cipherText</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">try</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">let</span> sm4 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM4</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">let</span> ctx <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM4_Context</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            ctx<span class="token punctuation">.</span>isPadding <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
            ctx<span class="token punctuation">.</span>mode <span class="token operator">=</span> sm4<span class="token punctuation">.</span><span class="token constant">SM4_ENCRYPT</span><span class="token punctuation">;</span>
            <span class="token keyword">let</span> keyBytes <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stringToByte</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>secretKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
            sm4<span class="token punctuation">.</span><span class="token function">sm4_setkey_dec</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> keyBytes<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">let</span> decrypted <span class="token operator">=</span> sm4<span class="token punctuation">.</span><span class="token function">sm4_crypt_ecb</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> base64js<span class="token punctuation">.</span><span class="token function">toByteArray</span><span class="token punctuation">(</span>cipherText<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">byteToString</span><span class="token punctuation">(</span>decrypted<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">// CBC模式加密</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">encryptData_CBC</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">plainText</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        <span class="token keyword">try</span><span class="token punctuation">&#123;</span>
            <span class="token keyword">const</span> sm4 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM4</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">const</span> ctx <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM4_Context</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            ctx<span class="token punctuation">.</span>isPadding <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
            ctx<span class="token punctuation">.</span>mode <span class="token operator">=</span> sm4<span class="token punctuation">.</span><span class="token constant">SM4_ENCRYPT</span><span class="token punctuation">;</span>

            <span class="token keyword">const</span> keyBytes <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stringToByte</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>secretKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">const</span> ivBytes <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stringToByte</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>iv<span class="token punctuation">)</span><span class="token punctuation">;</span>

            sm4<span class="token punctuation">.</span><span class="token function">sm4_setkey_enc</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> keyBytes<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">const</span> encrypted <span class="token operator">=</span> sm4<span class="token punctuation">.</span><span class="token function">sm4_crypt_cbc</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> ivBytes<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stringToByte</span><span class="token punctuation">(</span>plainText<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">const</span> cipherText <span class="token operator">=</span> base64js<span class="token punctuation">.</span><span class="token function">fromByteArray</span><span class="token punctuation">(</span>encrypted<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>cipherText <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> cipherText<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span>
            <span class="token punctuation">&#123;</span>
                cipherText<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">(\s*|\t|\r|\n)</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
            <span class="token keyword">return</span> cipherText<span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">catch</span> <span class="token punctuation">(</span> e<span class="token punctuation">)</span>
        <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token comment">//解密_CBC</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">decryptData_CBC</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">cipherText</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">try</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">let</span> sm4 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM4</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">let</span> ctx <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SM4_Context</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            ctx<span class="token punctuation">.</span>isPadding <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
            ctx<span class="token punctuation">.</span>mode <span class="token operator">=</span> sm4<span class="token punctuation">.</span><span class="token constant">SM4_ENCRYPT</span><span class="token punctuation">;</span>
            <span class="token keyword">let</span> keyBytes <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stringToByte</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>secretKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">let</span> ivBytes <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stringToByte</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>iv<span class="token punctuation">)</span><span class="token punctuation">;</span>
            sm4<span class="token punctuation">.</span><span class="token function">sm4_setkey_dec</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> keyBytes<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">let</span> decrypted <span class="token operator">=</span> sm4<span class="token punctuation">.</span><span class="token function">sm4_crypt_cbc</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> ivBytes<span class="token punctuation">,</span> base64js<span class="token punctuation">.</span><span class="token function">toByteArray</span><span class="token punctuation">(</span>cipherText<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">byteToString</span><span class="token punctuation">(</span>decrypted<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">stringToByte</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">str</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">const</span> bytes <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token keyword">let</span> len<span class="token punctuation">,</span> c<span class="token punctuation">;</span>
        len <span class="token operator">=</span> str<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
        <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            c <span class="token operator">=</span> str<span class="token punctuation">.</span><span class="token function">charCodeAt</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span><span class="token punctuation">(</span>c <span class="token operator">>=</span> <span class="token number">0x010000</span> <span class="token operator">&amp;&amp;</span> c <span class="token operator">&lt;=</span> <span class="token number">0x10FFFF</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                bytes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">(</span>c <span class="token operator">>></span> <span class="token number">18</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0x07</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token number">0xF0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                bytes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">(</span>c <span class="token operator">>></span> <span class="token number">12</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0x3F</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token number">0x80</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                bytes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">(</span>c <span class="token operator">>></span> <span class="token number">6</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0x3F</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token number">0x80</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                bytes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">(</span>c <span class="token operator">&amp;</span> <span class="token number">0x3F</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token number">0x80</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span>c <span class="token operator">>=</span> <span class="token number">0x000800</span> <span class="token operator">&amp;&amp;</span> c <span class="token operator">&lt;=</span> <span class="token number">0x00FFFF</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                bytes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">(</span>c <span class="token operator">>></span> <span class="token number">12</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0x0F</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token number">0xE0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                bytes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">(</span>c <span class="token operator">>></span> <span class="token number">6</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0x3F</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token number">0x80</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                bytes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">(</span>c <span class="token operator">&amp;</span> <span class="token number">0x3F</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token number">0x80</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span>c <span class="token operator">>=</span> <span class="token number">0x000080</span> <span class="token operator">&amp;&amp;</span> c <span class="token operator">&lt;=</span> <span class="token number">0x0007FF</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                bytes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">(</span>c <span class="token operator">>></span> <span class="token number">6</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0x1F</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token number">0xC0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                bytes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">(</span>c <span class="token operator">&amp;</span> <span class="token number">0x3F</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token number">0x80</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
                bytes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>c <span class="token operator">&amp;</span> <span class="token number">0xFF</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">return</span> bytes<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>


    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">byteToString</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">arr</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">typeof</span> arr <span class="token operator">===</span> <span class="token string">'string'</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> arr<span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">let</span> str <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">,</span>
            _arr <span class="token operator">=</span> arr<span class="token punctuation">;</span>
        <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> _arr<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">const</span> one <span class="token operator">=</span> _arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
                v <span class="token operator">=</span> one<span class="token punctuation">.</span><span class="token function">match</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^1+?(?=0)</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span><span class="token punctuation">(</span>v <span class="token operator">&amp;&amp;</span> one<span class="token punctuation">.</span>length <span class="token operator">===</span> <span class="token number">8</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                <span class="token keyword">const</span> bytesLength <span class="token operator">=</span> v<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>length<span class="token punctuation">;</span>
                <span class="token keyword">let</span> store <span class="token operator">=</span> _arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">7</span> <span class="token operator">-</span> bytesLength<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> st <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> st <span class="token operator">&lt;</span> bytesLength<span class="token punctuation">;</span> st<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                    store <span class="token operator">+=</span> _arr<span class="token punctuation">[</span>st <span class="token operator">+</span> i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">&#125;</span>
                str <span class="token operator">+=</span> String<span class="token punctuation">.</span><span class="token function">fromCharCode</span><span class="token punctuation">(</span><span class="token function">parseInt</span><span class="token punctuation">(</span>store<span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                i <span class="token operator">+=</span> bytesLength <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
                str <span class="token operator">+=</span> String<span class="token punctuation">.</span><span class="token function">fromCharCode</span><span class="token punctuation">(</span>_arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">return</span> str<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h2 id="CORS"><a href="#CORS" class="headerlink" title="CORS"></a>CORS</h2><p><strong>描述</strong></p>
<p>前后端分离的项目，为了保证正常访问，需设置跨域，由于配置不当：	</p>
<ol>
<li>CORS服务端的<code>Access-Control-Allow-Origin</code>设置为了*，并且<code>Access-Control-Allow-Credentials</code>设置为false。</li>
<li><code>Access-Control-Allow-Origin</code>设置不是固定的，而是根据用户跨域请求数据的Origin来定。不管<code>Access-Control-Allow-Credentials</code>设置为了true还是false，任何网站都可以发起请求，并读取对这些请求的响应。</li>
</ol>
<p>上述两种情况任何一个网站都可以发送跨域请求来获得CORS服务端上的数据，从而造成跨域漏洞。</p>
<p><strong>防护建议</strong></p>
<ol>
<li>配置白名单，仅允许指定的源来跨域请求服务器端的资源，并且服务器会响应。<br><code>Access-Control-Allow-Origin: https://xxxx.com</code><pre class="line-numbers language-nginx" data-language="nginx"><code class="language-nginx"><span class="token comment"># 定义合法的Origin列表 解决跨域问题</span>
<span class="token directive"><span class="token keyword">map</span> <span class="token variable">$http_origin</span> <span class="token variable">$allowed_origin</span></span> <span class="token punctuation">&#123;</span>
    <span class="token directive"><span class="token keyword">default</span> <span class="token number">0</span></span><span class="token punctuation">;</span>
    "~……http://10\.37\.169\.111(:[0-9+])?$" $http_origin<span class="token punctuation">;</span>
    "" <span class="token directive"><span class="token keyword">1</span></span><span class="token punctuation">;</span>
    "null" <span class="token directive"><span class="token keyword">1</span></span><span class="token punctuation">;</span> <span class="token comment"># 允许没有Origin的情况</span>
<span class="token punctuation">&#125;</span>
<span class="token directive"><span class="token keyword">location</span> /</span> <span class="token punctuation">&#123;</span>
    <span class="token comment"># ...其他配置</span>
    <span class="token directive"><span class="token keyword">if</span> (<span class="token variable">$allowed_origin</span> = 0)</span> <span class="token punctuation">&#123;</span>
        <span class="token directive"><span class="token keyword">return</span> <span class="token number">403</span> <span class="token string">"Invalid Origin"</span></span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token directive"><span class="token keyword">add_header</span> Access-Control-Allow-Origin <span class="token variable">$allowed_origin</span></span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></li>
<li>@CrossOrigin注解解决跨域问题，在需要允许跨域访问的接口或者类加上该注解就可以，如果用@RequestMapping，则要指定get，或post等才有起效。<br><code>@CrossOrigin(origins=&quot;http://localhost:4000&quot;)</code></li>
</ol>
<h2 id="XSS"><a href="#XSS" class="headerlink" title="XSS"></a>XSS</h2><p><strong>描述</strong></p>
<p>XSS的全称是跨站脚本攻击。它是一种将恶意脚本注入到其他用户信任的网站中的攻击方式。</p>
<ol>
<li>反射型XSS</li>
<li>存储型XSS</li>
<li>DOM型XSS</li>
</ol>
<p><strong>代码实现</strong></p>
<pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token comment">// 存储型xss</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">lombok<span class="token punctuation">.</span>extern<span class="token punctuation">.</span>slf4j<span class="token punctuation">.</span></span><span class="token class-name">Slf4j</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">StreamUtils</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span></span><span class="token class-name">ReadListener</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span></span><span class="token class-name">ServletInputStream</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>http<span class="token punctuation">.</span></span><span class="token class-name">HttpServletRequest</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>http<span class="token punctuation">.</span></span><span class="token class-name">HttpServletRequestWrapper</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">BufferedReader</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">ByteArrayInputStream</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">IOException</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">InputStreamReader</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token operator">*</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span>regex<span class="token punctuation">.</span></span><span class="token class-name">Pattern</span></span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@Slf4j</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">XssAndSqlHttpServletRequestWrapper</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServletRequestWrapper</span> <span class="token punctuation">&#123;</span>

    <span class="token class-name">HttpServletRequest</span> orgRequest <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">Map</span><span class="token operator">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">></span> parameterMap<span class="token punctuation">;</span>
    <span class="token comment">/**
     * 用于保存读取body中数据
      */</span>
    <span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> body<span class="token punctuation">;</span>

    <span class="token comment">/**
     * sql keywords pattern
     */</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> sqlKeywords <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span class="token string">"and"</span><span class="token punctuation">,</span> <span class="token string">"or"</span><span class="token punctuation">,</span> <span class="token string">"insert"</span><span class="token punctuation">,</span> <span class="token string">"select"</span><span class="token punctuation">,</span> <span class="token string">"delete"</span><span class="token punctuation">,</span> <span class="token string">"update"</span><span class="token punctuation">,</span> <span class="token string">"count"</span><span class="token punctuation">,</span> <span class="token string">"chr"</span><span class="token punctuation">,</span> <span class="token string">"mid"</span><span class="token punctuation">,</span> <span class="token string">"master"</span><span class="token punctuation">,</span> <span class="token string">"truncate"</span><span class="token punctuation">,</span> <span class="token string">"char"</span><span class="token punctuation">,</span> <span class="token string">"declare"</span><span class="token punctuation">,</span> <span class="token string">"backup"</span><span class="token punctuation">,</span> <span class="token string">"script"</span><span class="token punctuation">,</span> <span class="token string">"exec"</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>


    <span class="token comment">/**
     * xss pattern
     */</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">Pattern</span><span class="token punctuation">[</span><span class="token punctuation">]</span> patterns <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// Avoid anything between script tags</span>
        <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">"&lt;[\r\n| | ]*script[\r\n| | ]*>(.*?)&lt;/[\r\n| | ]*script[\r\n| | ]*>"</span><span class="token punctuation">,</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">CASE_INSENSITIVE</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token comment">// Remove any lonesome &lt;script ...> tag</span>
        <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">"&lt;[\r\n| | ]*script(.*?)>"</span><span class="token punctuation">,</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">CASE_INSENSITIVE</span> <span class="token operator">|</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">MULTILINE</span> <span class="token operator">|</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">DOTALL</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token comment">// Remove any lonesome &lt;/script> tag</span>
        <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">"&lt;/[\r\n| | ]*script[\r\n| | ]*>"</span><span class="token punctuation">,</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">CASE_INSENSITIVE</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token comment">// Avoid anything in a src="http://www.xxx.com/xx/java/..." type of expression</span>
        <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">"src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\'](.*?)[\\\"|\\\']"</span><span class="token punctuation">,</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">CASE_INSENSITIVE</span> <span class="token operator">|</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">MULTILINE</span> <span class="token operator">|</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">DOTALL</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token comment">// Avoid eval(...) expressions</span>
        <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">"eval\\((.*?)\\)"</span><span class="token punctuation">,</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">CASE_INSENSITIVE</span> <span class="token operator">|</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">MULTILINE</span> <span class="token operator">|</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">DOTALL</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token comment">// Avoid e-xpression(...) expressions</span>
        <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">"e-xpression\\((.*?)\\)"</span><span class="token punctuation">,</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">CASE_INSENSITIVE</span> <span class="token operator">|</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">MULTILINE</span> <span class="token operator">|</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">DOTALL</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token comment">// Avoid javaScript:... expressions</span>
        <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">"javascript[\r\n| | ]*:[\r\n| | ]*"</span><span class="token punctuation">,</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">CASE_INSENSITIVE</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token comment">// Avoid vbScript:... expressions</span>
        <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">"vbscript[\r\n| | ]*:[\r\n| | ]*"</span><span class="token punctuation">,</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">CASE_INSENSITIVE</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token comment">// Avoid onload= expressions</span>
        <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">"onload(.*?)="</span><span class="token punctuation">,</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">CASE_INSENSITIVE</span> <span class="token operator">|</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">MULTILINE</span> <span class="token operator">|</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">DOTALL</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token comment">// 特殊字符,不使用的特殊字符直接过滤掉，如果需要使用，不在这里配置，在下面转换为全角</span>
        <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">"[|&amp;;$%@',\"&lt;>()+*\\r\\n\\\\]"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">"(0x0a)|(0x0d)"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token comment">// 关键字</span>
        <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token function">addSqlKeyWords</span><span class="token punctuation">(</span>sqlKeywords<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">CASE_INSENSITIVE</span> <span class="token operator">|</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">MULTILINE</span> <span class="token operator">|</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token constant">DOTALL</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">addSqlKeyWords</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> map<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name">StringBuilder</span> sb <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StringBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">String</span> key<span class="token operator">:</span> map<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"("</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">" )"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"|"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        sb<span class="token punctuation">.</span><span class="token function">deleteCharAt</span><span class="token punctuation">(</span>sb<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> sb<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token keyword">public</span> <span class="token class-name">XssAndSqlHttpServletRequestWrapper</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> request<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">super</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">;</span>
        orgRequest <span class="token operator">=</span> request<span class="token punctuation">;</span>
        parameterMap <span class="token operator">=</span> request<span class="token punctuation">.</span><span class="token function">getParameterMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        body <span class="token operator">=</span> <span class="token class-name">StreamUtils</span><span class="token punctuation">.</span><span class="token function">copyToByteArray</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span><span class="token function">getInputStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">// 重写几个HttpServletRequestWrapper中的方法↓</span>

    <span class="token comment">/**
     * 获取所有参数名
     *
     * @return 返回所有参数名
     */</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">Enumeration</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">></span></span> <span class="token function">getParameterNames</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name">Vector</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">></span></span> vector <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vector</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">></span></span><span class="token punctuation">(</span>parameterMap<span class="token punctuation">.</span><span class="token function">keySet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> vector<span class="token punctuation">.</span><span class="token function">elements</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 覆盖getParameter方法，将参数名和参数值都做xss &amp; sql过滤。&lt;br/>
     * 如果需要获得原始的值，则通过super.getParameterValues(name)来获取&lt;br/>
     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
     */</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> results <span class="token operator">=</span> parameterMap<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>results <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> results<span class="token punctuation">.</span>length <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
            <span class="token class-name">String</span> value <span class="token operator">=</span> results<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>value <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                value <span class="token operator">=</span> <span class="token function">xssEncode</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
            <span class="token keyword">return</span> value<span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 获取指定参数名的所有值的数组，如：checkbox的所有数据 接收数组变量 ，如checkobx类型
     */</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">getParameterValues</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> results <span class="token operator">=</span> parameterMap<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>results <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> results<span class="token punctuation">.</span>length <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">int</span> length <span class="token operator">=</span> results<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
            <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                results<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">xssEncode</span><span class="token punctuation">(</span>results<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
            <span class="token keyword">return</span> results<span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 覆盖getHeader方法，将参数名和参数值都做xss &amp; sql过滤。&lt;br/>
     * 如果需要获得原始的值，则通过super.getHeaders(name)来获取&lt;br/>
     * getHeaderNames 也可能需要覆盖
     */</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>

        <span class="token class-name">String</span> value <span class="token operator">=</span> <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">getHeader</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>value <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            value <span class="token operator">=</span> <span class="token function">xssEncode</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">return</span> value<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 将容易引起xss &amp; sql漏洞的半角字符直接替换成全角字符
     *
     * @param s
     * @return
     */</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">xssEncode</span><span class="token punctuation">(</span><span class="token class-name">String</span> s<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>s <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> s<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> s<span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
            s <span class="token operator">=</span> <span class="token function">stripXSSAndSql</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token class-name">StringBuilder</span> sb <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StringBuilder</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">16</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> s<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">char</span> c <span class="token operator">=</span> s<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">switch</span> <span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                <span class="token keyword">case</span> <span class="token char">'>'</span><span class="token operator">:</span>
                    <span class="token comment">// 转义大于号</span>
                    sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"＞"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
                <span class="token keyword">case</span> <span class="token char">'&lt;'</span><span class="token operator">:</span>
                    <span class="token comment">// 转义小于号</span>
                    sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"＜"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
                <span class="token keyword">case</span> <span class="token char">'\''</span><span class="token operator">:</span>
                    <span class="token comment">// 转义单引号</span>
                    sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"＇"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
                <span class="token keyword">case</span> <span class="token char">'\"'</span><span class="token operator">:</span>
                    <span class="token comment">// 转义双引号</span>
                    sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"＂"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
                <span class="token keyword">case</span> <span class="token char">'&amp;'</span><span class="token operator">:</span>
                    <span class="token comment">// 转义&amp;</span>
                    sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"＆"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
                <span class="token keyword">case</span> <span class="token char">'#'</span><span class="token operator">:</span>
                    <span class="token comment">// 转义#</span>
                    sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"＃"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
                <span class="token keyword">case</span> <span class="token char">'('</span><span class="token operator">:</span>
                    <span class="token comment">// 转义#</span>
                    sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"（"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
                <span class="token keyword">case</span> <span class="token char">')'</span><span class="token operator">:</span>
                    <span class="token comment">// 转义#</span>
                    sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"）"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
                <span class="token keyword">case</span> <span class="token char">';'</span><span class="token operator">:</span>
                    <span class="token comment">// 转义#</span>
                    sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"；"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
                <span class="token keyword">default</span><span class="token operator">:</span>
                    sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">return</span> sb<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 获取最原始的request
     *
     * @return
     */</span>
    <span class="token keyword">public</span> <span class="token class-name">HttpServletRequest</span> <span class="token function">getOrgRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> orgRequest<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 获取最原始的request的静态方法
     *
     * @return
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">HttpServletRequest</span> <span class="token function">getOrgRequest</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>req <span class="token keyword">instanceof</span> <span class="token class-name">XssAndSqlHttpServletRequestWrapper</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token class-name">XssAndSqlHttpServletRequestWrapper</span><span class="token punctuation">)</span> req<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getOrgRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>

        <span class="token keyword">return</span> req<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/**
     * 防止xss跨脚本攻击（替换，根据实际情况调整）
     */</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">stripXSSAndSql</span><span class="token punctuation">(</span><span class="token class-name">String</span> value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>value <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">Pattern</span> pattern <span class="token operator">:</span> patterns<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                value <span class="token operator">=</span> pattern<span class="token punctuation">.</span><span class="token function">matcher</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replaceAll</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">return</span> value<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">checkXSSAndSql</span><span class="token punctuation">(</span><span class="token class-name">String</span> value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>value <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">Pattern</span> pattern <span class="token operator">:</span> patterns<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>pattern<span class="token punctuation">.</span><span class="token function">matcher</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                    <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
                <span class="token punctuation">&#125;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token keyword">boolean</span> <span class="token function">checkParameter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name">Map</span><span class="token operator">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">></span> submitParams <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token punctuation">(</span>parameterMap<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">Set</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">></span></span> submitNames <span class="token operator">=</span> submitParams<span class="token punctuation">.</span><span class="token function">keySet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">String</span> submitName <span class="token operator">:</span> submitNames<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token class-name">Object</span> submitValues <span class="token operator">=</span> submitParams<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>submitName<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>submitValues <span class="token keyword">instanceof</span> <span class="token class-name">String</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">checkXSSAndSql</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">)</span> submitValues<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                    <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
                <span class="token punctuation">&#125;</span>
            <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>submitValues <span class="token keyword">instanceof</span> <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">String</span> submitValue <span class="token operator">:</span> <span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> submitValues<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">checkXSSAndSql</span><span class="token punctuation">(</span>submitValue<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                        <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
                    <span class="token punctuation">&#125;</span>
                <span class="token punctuation">&#125;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">BufferedReader</span> <span class="token function">getReader</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">BufferedReader</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">InputStreamReader</span><span class="token punctuation">(</span><span class="token function">getInputStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">ServletInputStream</span> <span class="token function">getInputStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">final</span> <span class="token class-name">ByteArrayInputStream</span> bais <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ByteArrayInputStream</span><span class="token punctuation">(</span>body<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ServletInputStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>

            <span class="token annotation punctuation">@Override</span>
            <span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">read</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">&#123;</span>
                <span class="token keyword">return</span> bais<span class="token punctuation">.</span><span class="token function">read</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>

            <span class="token annotation punctuation">@Override</span>
            <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">isFinished</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>

            <span class="token annotation punctuation">@Override</span>
            <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">isReady</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>

            <span class="token annotation punctuation">@Override</span>
            <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setReadListener</span><span class="token punctuation">(</span><span class="token class-name">ReadListener</span> arg0<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token comment">// 过滤器中实现</span>
<span class="token annotation punctuation">@WebFilter</span><span class="token punctuation">(</span><span class="token string">"/*"</span><span class="token punctuation">)</span>  <span class="token comment">// 过滤所有请求</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">XSSFilter</span> <span class="token keyword">implements</span> <span class="token class-name">Filter</span> <span class="token punctuation">&#123;</span>
    
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token class-name">FilterConfig</span> filterConfig<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// 初始化代码</span>
    <span class="token punctuation">&#125;</span>
    
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">doFilter</span><span class="token punctuation">(</span><span class="token class-name">ServletRequest</span> request<span class="token punctuation">,</span> <span class="token class-name">ServletResponse</span> response<span class="token punctuation">,</span> 
                         <span class="token class-name">FilterChain</span> chain<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span><span class="token punctuation">,</span> <span class="token class-name">ServletException</span> <span class="token punctuation">&#123;</span>
        
        <span class="token class-name">HttpServletRequest</span> httpRequest <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span><span class="token punctuation">)</span> request<span class="token punctuation">;</span>
        
        <span class="token comment">// 创建包装器</span>
        <span class="token class-name">HttpServletRequest</span> wrappedRequest <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XssAndSqlHttpServletRequestWrapper</span><span class="token punctuation">(</span>httpRequest<span class="token punctuation">)</span><span class="token punctuation">;</span>
        
        <span class="token comment">// 继续过滤器链，传递包装后的请求</span>
        chain<span class="token punctuation">.</span><span class="token function">doFilter</span><span class="token punctuation">(</span>wrappedRequest<span class="token punctuation">,</span> response<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">destroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// 清理代码</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h2 id="CSRF"><a href="#CSRF" class="headerlink" title="CSRF"></a>CSRF</h2><p><strong>描述</strong></p>
<p>CSRF，全称Cross-site request forgery，即跨站请求伪造，是指利用受害者尚未失效的身份认证信息（cookie、会话等），诱骗其点击恶意链接或者访问包含攻击代码的页面，在受害人不知情的情况下以受害者的身份向（身份认证信息所对应的）服务器发送请求，从而完成非法操作（如转账、改密等）。</p>
<p><strong>防护建议</strong></p>
<ol>
<li>验证HTTP referer字段<br>在后端程序接收到请求时，应检查请求的来源地址（HTTP Referer）是否合法（利用白名单），如果请求来源不在指定的名单中，即视为CSRF。<pre class="line-numbers language-nginx" data-language="nginx"><code class="language-nginx"><span class="token comment"># 定义合法的Referer</span>
<span class="token comment"># none:允许没有Referer头的请求。blocked:允许Referer头存在但值被防火墙或代理服务器修改、删除（值为空）的请求。server_names:允许Referer头与server_name中定义的其中一个域名匹配的请求。</span>
<span class="token comment"># 如果配置不管用,可以看下location里面的配置</span>
<span class="token directive"><span class="token keyword">valid_referers</span> none blocked server_names yoursite.com *.trusted-site.com</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">if</span> (<span class="token variable">$invalid_referer</span>)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment"># 返回403禁止访问</span>
    <span class="token directive"><span class="token keyword">return</span> <span class="token number">403</span></span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token comment"># location块referer配置(后端代码没有referer配置的话 启用nginx referer配置)</span>
<span class="token directive"><span class="token keyword">set</span> <span class="token variable">$allow_referer</span> <span class="token number">1</span></span><span class="token punctuation">;</span>

<span class="token directive"><span class="token keyword">if($http_referer</span> !~ <span class="token string">"^http://10\.39\.169\.22(:[0-9]+)?"</span>)</span> <span class="token punctuation">&#123;</span>
    <span class="token directive"><span class="token keyword">set</span> <span class="token variable">$allow_referer</span> <span class="token number">0</span></span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token directive"><span class="token keyword">if($allow_referer</span> = 0)</span><span class="token punctuation">&#123;</span>
    return 403
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></li>
<li>随机token<br>对于敏感的网页，可在请求参数或者请求header中增加不可伪造的token等信息用户防护CSRF攻击(可利用防重放攻击中的sign当作token)。</li>
</ol>
<h2 id="SQL注入"><a href="#SQL注入" class="headerlink" title="SQL注入"></a>SQL注入</h2><p><strong>代码实现</strong></p>
<pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Enumeration</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Locale</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span>regex<span class="token punctuation">.</span></span><span class="token class-name">Matcher</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span>regex<span class="token punctuation">.</span></span><span class="token class-name">Pattern</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>http<span class="token punctuation">.</span></span><span class="token class-name">HttpServletRequest</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">javax<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>http<span class="token punctuation">.</span></span><span class="token class-name">HttpServletResponse</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>commons<span class="token punctuation">.</span>lang3<span class="token punctuation">.</span></span><span class="token class-name">StringUtils</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>web<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span></span><span class="token class-name">HandlerInterceptor</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>web<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span></span><span class="token class-name">ModelAndView</span></span><span class="token punctuation">;</span>
<span class="token comment">/**
 * sql注入拦截
 */</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SQLInterceptor</span> <span class="token keyword">implements</span> <span class="token class-name">HandlerInterceptor</span> <span class="token punctuation">&#123;</span>

	<span class="token annotation punctuation">@Override</span>
	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">afterCompletion</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> arg0<span class="token punctuation">,</span>
			<span class="token class-name">HttpServletResponse</span> arg1<span class="token punctuation">,</span> <span class="token class-name">Object</span> arg2<span class="token punctuation">,</span> <span class="token class-name">Exception</span> arg3<span class="token punctuation">)</span>
    <span class="token punctuation">&#123;</span>
	
	<span class="token punctuation">&#125;</span>

	<span class="token annotation punctuation">@Override</span>
	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">postHandle</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> arg0<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> arg1<span class="token punctuation">,</span>
			<span class="token class-name">Object</span> arg2<span class="token punctuation">,</span> <span class="token class-name">ModelAndView</span> arg3<span class="token punctuation">)</span>  <span class="token punctuation">&#123;</span>
		
	<span class="token punctuation">&#125;</span>

	<span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">preHandle</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> arg0<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> arg1<span class="token punctuation">,</span> <span class="token class-name">Object</span> arg2<span class="token punctuation">)</span>  <span class="token punctuation">&#123;</span>
		<span class="token class-name">Enumeration</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">></span></span> names <span class="token operator">=</span> arg0<span class="token punctuation">.</span><span class="token function">getParameterNames</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  
        <span class="token keyword">while</span><span class="token punctuation">(</span>names<span class="token punctuation">.</span><span class="token function">hasMoreElements</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>  
            <span class="token class-name">String</span> name <span class="token operator">=</span> names<span class="token punctuation">.</span><span class="token function">nextElement</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  
            <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> values <span class="token operator">=</span> arg0<span class="token punctuation">.</span><span class="token function">getParameterValues</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span><span class="token punctuation">(</span>values<span class="token operator">!=</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token class-name">String</span> value<span class="token operator">:</span> values<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                    <span class="token comment">//sql注入直接拦截</span>
                    <span class="token class-name">Locale</span><span class="token punctuation">.</span><span class="token function">setDefault</span><span class="token punctuation">(</span><span class="token class-name">Locale</span><span class="token punctuation">.</span><span class="token constant">ENGLISH</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">judgeSQLInject</span><span class="token punctuation">(</span>value<span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                        <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
                    <span class="token punctuation">&#125;</span>
                    <span class="token comment">//跨站xss清理</span>
                    <span class="token function">clearXss</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">&#125;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>  
        <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>  
	<span class="token punctuation">&#125;</span>
	
	<span class="token comment">/**
	 * 校验sql注入字符串
	 */</span>
    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">judgeSQLInject</span><span class="token punctuation">(</span><span class="token class-name">String</span> value<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>  
        <span class="token keyword">if</span><span class="token punctuation">(</span>value <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> <span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isBlank</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> 
        <span class="token comment">//insert|and|or|select|update|delete|drop|truncate|%20|=|--|;|'|%|#|+|,|//|/|\\|!=|(|)</span>
<span class="token comment">//        String sqlStr = ">|&lt;|script| insert | and | or | select | update | delete | drop | truncate |%20|-|--|'|%|+|//|/|\\|!=|(|)";</span>
        <span class="token class-name">String</span> sqlStr <span class="token operator">=</span> <span class="token string">">|&lt;|script| insert | and | or | select | update | delete | drop | truncate |%20|--|%|+|//|\\|!=|(|)"</span><span class="token punctuation">;</span>  
        <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> sqlArr <span class="token operator">=</span> sqlStr<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">"\\|"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  
        <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span>i<span class="token operator">&lt;</span>sqlArr<span class="token punctuation">.</span>length<span class="token punctuation">;</span>i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>  
            <span class="token keyword">if</span><span class="token punctuation">(</span>value<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span>sqlArr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">></span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
            	<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">isSpecialParam</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>

            		<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>	
            	<span class="token punctuation">&#125;</span>
            <span class="token punctuation">&#125;</span>  
        <span class="token punctuation">&#125;</span>  
        <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>  
    <span class="token punctuation">&#125;</span>
    
    <span class="token comment">/**
     * 针对用到的必要特殊参数字符在此判断
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">isSpecialParam</span><span class="token punctuation">(</span><span class="token class-name">String</span> value<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    	<span class="token keyword">boolean</span> isSpecial <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span><span class="token comment">//是否为特殊字符串</span>
<span class="token comment">//    	Pattern pattern = Pattern.compile("[0-9]-[0-9]|.*image/octet-stream;base64.*|[0-9] [0-9]");</span>
    	<span class="token class-name">Pattern</span> pattern <span class="token operator">=</span> <span class="token class-name">Pattern</span><span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">".*image/octet-stream;base64.*"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token class-name">Matcher</span> matcher <span class="token operator">=</span> pattern<span class="token punctuation">.</span><span class="token function">matcher</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span><span class="token punctuation">(</span>matcher<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
			isSpecial <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
		<span class="token punctuation">&#125;</span>
		<span class="token keyword">return</span> isSpecial<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    
    <span class="token comment">/**
     * 处理跨站xss字符转义
     */</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> <span class="token function">clearXss</span><span class="token punctuation">(</span><span class="token class-name">String</span> value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>value <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> <span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isBlank</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> value<span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        value <span class="token operator">=</span> value<span class="token punctuation">.</span><span class="token function">replaceAll</span><span class="token punctuation">(</span><span class="token string">"&lt;"</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replaceAll</span><span class="token punctuation">(</span><span class="token string">">"</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token string">"'"</span><span class="token punctuation">,</span><span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        value <span class="token operator">=</span> value<span class="token punctuation">.</span><span class="token function">replaceAll</span><span class="token punctuation">(</span><span class="token string">"eval\\((.*)\\)"</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        value <span class="token operator">=</span> value<span class="token punctuation">.</span><span class="token function">replaceAll</span><span class="token punctuation">(</span><span class="token string">"[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']"</span><span class="token punctuation">,</span>
                <span class="token string">"\"\""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        value <span class="token operator">=</span> value<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token string">"script"</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> value<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>




                
            </div>
            <hr/>

            

    <div class="reprint" id="reprint-statement">
        
            <div class="reprint__author">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-user">
                        文章作者:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="/blog/about" rel="external nofollow noreferrer">xmxe</a>
                </span>
            </div>
            <div class="reprint__type">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-link">
                        文章链接:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="https://xmxe.github.io/blog/posts/33612673cd2d/">https://xmxe.github.io/blog/posts/33612673cd2d/</a>
                </span>
            </div>
            <div class="reprint__notice">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-copyright">
                        版权声明:
                    </i>
                </span>
                <span class="reprint-info">
                    本博客所有文章除特別声明外，均采用
                    <a href="https://creativecommons.org/licenses/by/4.0/deed.zh" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a>
                    许可协议。转载请注明来源
                    <a href="/blog/about" target="_blank">xmxe</a>
                    !
                </span>
            </div>
        
    </div>

    <script async defer>
      document.addEventListener("copy", function (e) {
        let toastHTML = '<span>复制成功，请遵循本文的转载规则</span><button class="btn-flat toast-action" onclick="navToReprintStatement()" style="font-size: smaller">查看</a>';
        M.toast({html: toastHTML})
      });

      function navToReprintStatement() {
        $("html, body").animate({scrollTop: $("#reprint-statement").offset().top - 80}, 800);
      }
    </script>



            <div class="tag_share" style="display: block;">
                <div class="post-meta__tag-list" style="display: inline-block;">
                    
                        <div class="article-tag">
                            
                                <a href="/blog/tags/%E4%BB%A3%E7%A0%81%E5%AE%9E%E6%88%98/">
                                    <span class="chip bg-color">代码实战</span>
                                </a>
                            
                        </div>
                    
                </div>
                <div class="post_share" style="zoom: 80%; width: fit-content; display: inline-block; float: right; margin: -0.15rem 0;">
                    <link rel="stylesheet" type="text/css" href="/blog/libs/share/css/share.min.css">
<div id="article-share">

    
    <div class="social-share" data-sites="qq,qzone,wechat,weibo,douban" data-wechat-qrcode-helper="<p>微信扫一扫即可分享！</p>"></div>
    <script src="/blog/libs/share/js/social-share.min.js"></script>
    

    

</div>

                </div>
            </div>
            
                <style>
    #reward {
        margin: 40px 0;
        text-align: center;
    }

    #reward .reward-link {
        font-size: 1.4rem;
        line-height: 38px;
    }

    #reward .btn-floating:hover {
        box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2), 0 5px 15px rgba(0, 0, 0, 0.2);
    }

    #rewardModal {
        width: 320px;
        height: 350px;
    }

    #rewardModal .reward-title {
        margin: 15px auto;
        padding-bottom: 5px;
    }

    #rewardModal .modal-content {
        padding: 10px;
    }

    #rewardModal .close {
        position: absolute;
        right: 15px;
        top: 15px;
        color: rgba(0, 0, 0, 0.5);
        font-size: 1.3rem;
        line-height: 20px;
        cursor: pointer;
    }

    #rewardModal .close:hover {
        color: #ef5350;
        transform: scale(1.3);
        -moz-transform:scale(1.3);
        -webkit-transform:scale(1.3);
        -o-transform:scale(1.3);
    }

    #rewardModal .reward-tabs {
        margin: 0 auto;
        width: 210px;
    }

    .reward-tabs .tabs {
        height: 38px;
        margin: 10px auto;
        padding-left: 0;
    }

    .reward-content ul {
        padding-left: 0 !important;
    }

    .reward-tabs .tabs .tab {
        height: 38px;
        line-height: 38px;
    }

    .reward-tabs .tab a {
        color: #fff;
        background-color: #ccc;
    }

    .reward-tabs .tab a:hover {
        background-color: #ccc;
        color: #fff;
    }

    .reward-tabs .wechat-tab .active {
        color: #fff !important;
        background-color: #22AB38 !important;
    }

    .reward-tabs .alipay-tab .active {
        color: #fff !important;
        background-color: #019FE8 !important;
    }

    .reward-tabs .reward-img {
        width: 210px;
        height: 210px;
    }
</style>

<div id="reward">
    <a href="#rewardModal" class="reward-link modal-trigger btn-floating btn-medium waves-effect waves-light red">赏</a>

    <!-- Modal Structure -->
    <div id="rewardModal" class="modal">
        <div class="modal-content">
            <a class="close modal-close"><i class="fas fa-times"></i></a>
            <h4 class="reward-title">你的赏识是我前进的动力</h4>
            <div class="reward-content">
                <div class="reward-tabs">
                    <ul class="tabs row">
                        <li class="tab col s6 alipay-tab waves-effect waves-light"><a href="#alipay">支付宝</a></li>
                        <li class="tab col s6 wechat-tab waves-effect waves-light"><a href="#wechat">微 信</a></li>
                    </ul>
                    <div id="alipay">
                        
                            <img src="/blog/medias/reward/alipay.jpg" class="reward-img" alt="支付宝打赏二维码">
                        
                    </div>
                    <div id="wechat">
                        
                            <img src="/blog/medias/reward/wechat.jpg" class="reward-img" alt="微信打赏二维码">
                        
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
    $(function () {
        $('.tabs').tabs();
    });
</script>

            
        </div>
    </div>

    

    

    

    

    

    

    

    

<article id="prenext-posts" class="prev-next articles">
    <div class="row article-row">
        
        <div class="article col s12 m6" data-aos="fade-up" data-aos="fade-up">
            <div class="article-badge left-badge text-color">
                <i class="far fa-dot-circle"></i>&nbsp;本篇
            </div>
            <div class="card">
                <a href="/blog/posts/33612673cd2d/">
                    <div class="card-image">
                        
                        <img src="https://img95.699pic.com/photo/32213/1132.jpg_wh860.jpg" class="responsive-img" alt="Web项目中的安全设计">
                        
                        <span class="card-title">Web项目中的安全设计</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            完整性校验描述
数据传输完整性是指数据在传输过程中，不被未授权的篡改或在篡改后能够被迅速发现。
防护建议

传输过程中数据做整体加密处理（该方案存在一定风险，若攻击者拥有系统访问权限，可在数据未解密的情况下直接篡改加密数据，进行提权操作，固
                        
                        
                    </div>
                    <div class="publish-info">
                        <span class="publish-date">
                            <!--
                            <i class="far fa-clock fa-fw icon-date"></i>2025-11-27
                            -->
                            
                                <i class="fas fa-user fa-fw"></i>
                                <a href="/blog/about" >
                                    xmxe
                                </a>
                            
                        </span>
                        <span class="publish-author">
                            
                                
                                
                                <a href="/blog/tags/%E4%BB%A3%E7%A0%81%E5%AE%9E%E6%88%98/">
                                    <span class="chip bg-color">代码实战</span>
                                </a>
                                
                            
                            
                        </span>
                    </div>
                </div>

            </div>
        </div>
        
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge right-badge text-color">
                下一篇&nbsp;<i class="fas fa-chevron-right"></i>
            </div>
            <div class="card">
                <a href="/blog/posts/69be9f826425/">
                    <div class="card-image">
                        
                        <img src="https://img-blog.csdnimg.cn/img_convert/01a0a5146f3c0237227168cefcd0d0bd.png" class="responsive-img" alt="消息队列技术选型">
                        
                        <span class="card-title">消息队列技术选型</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            Kafka
Kafka是LinkedIn开源的一个分布式流式处理平台，已经成为Apache顶级项目，早期被用来用于处理海量的日志，后面才慢慢发展成了一款功能全面的高性能消息队列。流式处理平台具有三个关键功能：

消息队列：发布和订阅消息流，
                        
                        
                    </div>
                    <div class="publish-info">
                        <span class="publish-date">
                            <!--
                            <i class="far fa-clock fa-fw icon-date"></i>2024-07-19
                            -->
                            
                                <i class="fas fa-user fa-fw"></i>
                                <a href="/blog/about" >
                                    xmxe
                                </a>
                            
                        </span>
                        <span class="publish-author">
                            
                                <i class="fas fa-bookmark fa-fw icon-category"></i>
                                
                                    <a href="/blog/categories/%E6%8A%80%E6%9C%AF%E6%A0%88/" class="post-category">
                                        技术栈
                                    </a>
                                
                            
                        </span>
                    </div>
                </div>
                
            </div>
        </div>
        
    </div>
</article>

</div>



<!-- 代码块功能依赖 -->
<script type="text/javascript" src="/blog/libs/codeBlock/codeBlockFuction.js"></script>

<!-- 代码语言 -->

<script type="text/javascript" src="/blog/libs/codeBlock/codeLang.js"></script>


<!-- 代码块复制 -->

<script type="text/javascript" src="/blog/libs/codeBlock/codeCopy.js"></script>


<!-- 代码块收缩 -->

<script type="text/javascript" src="/blog/libs/codeBlock/codeShrink.js"></script>


    </div>
    <div id="toc-aside" class="expanded col l3 hide-on-med-and-down">
        <div class="toc-widget card">
            <div class="toc-title"><i class="far fa-list-alt"></i>&nbsp;&nbsp;目录</div>
            <div id="toc-content"></div>
        </div>
    </div>
</div>

<!-- TOC 悬浮按钮. -->

<div id="floating-toc-btn" class="hide-on-med-and-down">
    <a class="btn-floating btn-large bg-color">
        <i class="fas fa-list-ul"></i>
    </a>
</div>


<script src="/blog/libs/tocbot/tocbot.min.js"></script>
<script>
    $(function () {
        tocbot.init({
            tocSelector: '#toc-content',
            contentSelector: '#articleContent',
            headingsOffset: -($(window).height() * 0.4 - 45),
            collapseDepth: Number('0'),
            headingSelector: 'h1, h2, h3, h4, h5, h6'
        });

        // modify the toc link href to support Chinese.
        let i = 0;
        let tocHeading = 'toc-heading-';
        $('#toc-content a').each(function () {
            $(this).attr('href', '#' + tocHeading + (++i));
        });

        // modify the heading title id to support Chinese.
        i = 0;
        $('#articleContent').children('h1, h2, h3, h4, h5, h6').each(function () {
            $(this).attr('id', tocHeading + (++i));
        });

        // Set scroll toc fixed.
        let tocHeight = parseInt($(window).height() * 0.4 - 64);
        let $tocWidget = $('.toc-widget');
        $(window).scroll(function () {
            let scroll = $(window).scrollTop();
            /* add post toc fixed. */
            if (scroll > tocHeight) {
                $tocWidget.addClass('toc-fixed');
            } else {
                $tocWidget.removeClass('toc-fixed');
            }
        });

        
        /* 修复文章卡片 div 的宽度. */
        let fixPostCardWidth = function (srcId, targetId) {
            let srcDiv = $('#' + srcId);
            if (srcDiv.length === 0) {
                return;
            }

            let w = srcDiv.width();
            if (w >= 450) {
                w = w + 21;
            } else if (w >= 350 && w < 450) {
                w = w + 18;
            } else if (w >= 300 && w < 350) {
                w = w + 16;
            } else {
                w = w + 14;
            }
            $('#' + targetId).width(w);
        };

        // 切换TOC目录展开收缩的相关操作.
        const expandedClass = 'expanded';
        let $tocAside = $('#toc-aside');
        let $mainContent = $('#main-content');
        $('#floating-toc-btn .btn-floating').click(function () {
            if ($tocAside.hasClass(expandedClass)) {
                $tocAside.removeClass(expandedClass).hide();
                $mainContent.removeClass('l9');
            } else {
                $tocAside.addClass(expandedClass).show();
                $mainContent.addClass('l9');
            }
            fixPostCardWidth('artDetail', 'prenext-posts');
        });
        
    });
</script>

    

</main>




    <footer class="page-footer bg-color">
    
        <link rel="stylesheet" href="/blog/libs/aplayer/APlayer.min.css">
<style>
    .aplayer .aplayer-lrc p {
        
        display: none;
        
        font-size: 12px;
        font-weight: 700;
        line-height: 16px !important;
    }

    .aplayer .aplayer-lrc p.aplayer-lrc-current {
        
        display: none;
        
        font-size: 15px;
        color: #42b983;
    }

    
    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body {
        left: -66px !important;
    }

    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body:hover {
        left: 0px !important;
    }

    
</style>
<div class="">
    
    <div class="row">
        <meting-js class="col l8 offset-l2 m10 offset-m1 s12"
                   server="netease"
                   type="song"
                   id="569200213"
                   fixed='true'
                   autoplay='false'
                   theme='#42b983'
                   loop='all'
                   order='random'
                   preload='auto'
                   volume='0.7'
                   list-folded='true'
        >
        </meting-js>
    </div>
</div>

<script src="/blog/libs/aplayer/APlayer.min.js"></script>
<!-- <script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script> -->

    
    <div class="container row center-align" style="margin-bottom: 0px !important;">
        <div class="col s12 m8 l8 copy-right">
            Copyright&nbsp;&copy;
            
            
                <span id="year">2022-2025
                </span>
            
            

            <a href="/blog/about" target="_blank">
                xmxe
            </a>
            |&nbsp;Powered by&nbsp;
            <a href="https://hexo.io/" target="_blank">Hexo</a>
            |&nbsp;Theme&nbsp;
            <a href="https://github.com/blinkfox/hexo-theme-matery" target="_blank">Matery</a>
            <br>

            
            
            
            
            
            

            
            <br>

            
            <br>

            
        </div>
        <div class="col s12 m4 l4 social-link2 ">
    <a href="https://github.com/xmxe" class="tooltipped" target="_blank" data-tooltip="GitHub" data-position="top" data-delay="50">
        <i class="fab fa-github"></i>
    </a>



    <a href="https://gitee.com/xmxe" class="tooltipped" target="_blank" data-tooltip="码云" data-position="top" data-delay="50">
        <svg width="19" height="19" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" style="position: relative; top: 2px; left: 0.5px;">
            <path d="M512 1024C230.4 1024 0 793.6 0 512S230.4 0 512 0s512 230.4 512 512-230.4 512-512 512z m259.2-569.6H480c-12.8 0-25.6 12.8-25.6 25.6v64c0 12.8 12.8 25.6 25.6 25.6h176c12.8 0 25.6 12.8 25.6 25.6v12.8c0 41.6-35.2 76.8-76.8 76.8h-240c-12.8 0-25.6-12.8-25.6-25.6V416c0-41.6 35.2-76.8 76.8-76.8h355.2c12.8 0 25.6-12.8 25.6-25.6v-64c0-12.8-12.8-25.6-25.6-25.6H416c-105.6 0-188.8 86.4-188.8 188.8V768c0 12.8 12.8 25.6 25.6 25.6h374.4c92.8 0 169.6-76.8 169.6-169.6v-144c0-12.8-12.8-25.6-25.6-25.6z" fill="#fff">
            </path>
        </svg>
    </a>

















    
        
          <a href="/blog/download" class="tooltipped" target="_blank" data-tooltip="下载" data-position="top" data-delay="50">
            <i class="fas fa-download"></i>
          </a>
        
    



    <style>
  .mobiledevice {
    display: none !important;
  }

  footer .wechat_qrcode {
    position: fixed;
  }

  /*微信二维码*/
  .wechat_qrcode {
    position: absolute;
    margin-left: 10px;
    bottom: 10px;
    background: url("/blog/medias/xcx.png");
    zoom:40%;
  }

  .wechat:hover .wechat_qrcode {
    width: 430px;
    height: 430px;
    animation: move 0.4s linear 1 normal;
  }

  @keyframes move {
    0% {
      transform: translate(100px, 0);
      opacity: 0;
    }
    50% {
      transform: translate(50px, 0);
      opacity: 0.5;
    }
    100% {
      transform: translate(0, 0);
      opacity: 1;
    }
  }

  @media only screen and (max-width: 601px) {
    .wechat {
      display: none !important;
    }
    .mobiledevice {
      display: inline-block !important;
    }
  }
</style>

<a href="javascript:;" class="wechat" data-position="top" data-delay="50">
  <i class="fab fa-weixin"></i>
  <img class="wechat_qrcode" />
</a>

<a
  href="javascript:;"
  class="tooltipped mobiledevice"
  data-tooltip="微信: 464817304"
  data-position="top"
  data-delay="50"
>
  <i class="fab fa-weixin"></i>
</a>

</div>
    </div>
</footer>

<div class="progress-bar"></div>


    <!-- 搜索遮罩框 -->
<div id="searchModal" class="modal">
    <div class="modal-content">
        <div class="search-header">
            <span class="title"><i class="fas fa-search"></i>&nbsp;&nbsp;搜索</span>
            <input type="search" id="searchInput" name="s" placeholder="请输入搜索的关键字"
                   class="search-input">
        </div>
        <div id="searchResult"></div>
    </div>
</div>

<script type="text/javascript">
$(function () {
    var searchFunc = function (path, search_id, content_id) {
        'use strict';
        $.ajax({
            url: path,
            dataType: "xml",
            success: function (xmlResponse) {
                // get the contents from search data
                var datas = $("entry", xmlResponse).map(function () {
                    return {
                        title: $("title", this).text(),
                        content: $("content", this).text(),
                        url: $("url", this).text()
                    };
                }).get();
                var $input = document.getElementById(search_id);
                var $resultContent = document.getElementById(content_id);
                $input.addEventListener('input', function () {
                    var str = '<ul class=\"search-result-list\">';
                    var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
                    $resultContent.innerHTML = "";
                    if (this.value.trim().length <= 0) {
                        return;
                    }
                    // perform local searching
                    datas.forEach(function (data) {
                        var isMatch = true;
                        var data_title = data.title.trim().toLowerCase();
                        var data_content = data.content.trim().replace(/<[^>]+>/g, "").toLowerCase();
                        var data_url = data.url;
                        data_url = data_url.indexOf('/') === 0 ? data.url : '/' + data_url;
                        var index_title = -1;
                        var index_content = -1;
                        var first_occur = -1;
                        // only match artiles with not empty titles and contents
                        if (data_title !== '' && data_content !== '') {
                            keywords.forEach(function (keyword, i) {
                                index_title = data_title.indexOf(keyword);
                                index_content = data_content.indexOf(keyword);
                                if (index_title < 0 && index_content < 0) {
                                    isMatch = false;
                                } else {
                                    if (index_content < 0) {
                                        index_content = 0;
                                    }
                                    if (i === 0) {
                                        first_occur = index_content;
                                    }
                                }
                            });
                        }
                        // show search results
                        if (isMatch) {
                            str += "<li><a href='" + data_url + "' class='search-result-title'>" + data_title + "</a>";
                            var content = data.content.trim().replace(/<[^>]+>/g, "");
                            if (first_occur >= 0) {
                                // cut out 100 characters
                                var start = first_occur - 20;
                                var end = first_occur + 80;
                                if (start < 0) {
                                    start = 0;
                                }
                                if (start === 0) {
                                    end = 100;
                                }
                                if (end > content.length) {
                                    end = content.length;
                                }
                                var match_content = content.substr(start, end);
                                // highlight all keywords
                                keywords.forEach(function (keyword) {
                                    var regS = new RegExp(keyword, "gi");
                                    match_content = match_content.replace(regS, "<em class=\"search-keyword\">" + keyword + "</em>");
                                });

                                str += "<p class=\"search-result\">" + match_content + "...</p>"
                            }
                            str += "</li>";
                        }
                    });
                    str += "</ul>";
                    $resultContent.innerHTML = str;
                });
            }
        });
    };

    searchFunc('/blog/search.xml', 'searchInput', 'searchResult');
});
</script>

    <!-- 回到顶部按钮 -->
<div id="backTop" class="top-scroll">
    <a class="btn-floating btn-large waves-effect waves-light" href="#!">
        <i class="fas fa-arrow-up"></i>
    </a>
</div>

    <div class="stars-con">
  <div id="stars"></div>
  <div id="stars2"></div>
  <div id="stars3"></div>  
</div>

<!-- 白天和黑夜主题 -->



<script>
  function switchNightMode() {
    
      setTimeout(function () {
        $('body').hasClass('DarkMode') 
        ? ($('body').removeClass('DarkMode'), localStorage.setItem('isDark', '0'), $('#sum-moon-icon').removeClass("fa-sun").addClass('fa-moon')) 
        : ($('body').addClass('DarkMode'), localStorage.setItem('isDark', '1'), $('#sum-moon-icon').addClass("fa-sun").removeClass('fa-moon')),
          
        setTimeout(function () {
          $('.Cuteen_DarkSky').fadeOut(1e3, function () {
            $(this).remove()
          })
        }, 2e3)
      })
  }
</script>
    
    
    <script>
        /* 模式判断 */
        if (localStorage.getItem('isDark') === '1') {
            document.body.classList.add('DarkMode');
            $('#sum-moon-icon').addClass("fa-sun").removeClass('fa-moon')
        } else {
            document.body.classList.remove('DarkMode');
            $('#sum-moon-icon').removeClass("fa-sun").addClass('fa-moon')
        }
    </script>

    <script src="/blog/libs/materialize/materialize.min.js"></script>
    <script src="/blog/libs/masonry/masonry.pkgd.min.js"></script>
    <script src="/blog/libs/aos/aos.js"></script>
    <script src="/blog/libs/scrollprogress/scrollProgress.min.js"></script>
    <script src="/blog/libs/lightGallery/js/lightgallery-all.min.js"></script>
    <script src="/blog/js/matery.js"></script>

    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    

    

    

	
    

    

    
    <script type="text/javascript" src="/blog/libs/background/ribbon-dynamic.js" async="async"></script>
    

    

    <!-- 冒泡 -->
    
    <script type="text/javascript">
        // 只在桌面版网页启用特效
        // var windowWidth = $(window).width();
        
            document.write('<script type="text/javascript" src="/blog/libs/others/bubleAll.js"><\/script>');
        
        
    </script>
    

    <!-- 弹出文字 -->
    

</body>

</html>
